package com.njtoyo.taxi.admin.service.business.ride.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.*;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.netrides.entity.RideSubstitution;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.handler.FilterHandler;
import com.njtoyo.taxi.admin.handler.rule.online_valuation.OnlineValuationTimeMatcherHandler;
import com.njtoyo.taxi.admin.handler.rule.online_valuation.domain.RuleDetail;
import com.njtoyo.taxi.admin.library.common.Enum;
import com.njtoyo.taxi.admin.library.common.GeoPoint;
import com.njtoyo.taxi.admin.library.common.OperationRecordHelper;
import com.njtoyo.taxi.admin.library.common.util.CopyUtil;
import com.njtoyo.taxi.admin.library.payment.cmb.CmbPayClient;
import com.njtoyo.taxi.admin.library.taxi_service.TaxiService;
import com.njtoyo.taxi.admin.logic.business.RechargeLogic;
import com.njtoyo.taxi.admin.logic.business.driver.DriverLogic;
import com.njtoyo.taxi.admin.logic.business.order_refund.RefundService;
import com.njtoyo.taxi.admin.logic.business.ride.*;
import com.njtoyo.taxi.admin.logic.business.simple_call.RideTransactionLogLogic;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.SimpleCallRideState;
import com.njtoyo.taxi.admin.mapper.master.enums.*;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.mongo.entity.primary.CallRouteMongo;
import com.njtoyo.taxi.admin.mongo.entity.primary.RideRouteMongo;
import com.njtoyo.taxi.admin.mongo.repository.primary.CallRouteMongoRepository;
import com.njtoyo.taxi.admin.mongo.repository.primary.RideRouteRepository;
import com.njtoyo.taxi.admin.rest.pojo.dto.rule.online_price_rule.OnlinePriceFlagDto;
import com.njtoyo.taxi.admin.rest.presenter.business.ride.*;
import com.njtoyo.taxi.admin.rest.wrapper.business.ride.*;
import com.njtoyo.taxi.admin.service.business.DesignatedService;
import com.njtoyo.taxi.admin.service.business.SimpleCallRideService;
import com.njtoyo.taxi.admin.service.business.ride.RideService;
import com.njtoyo.taxi.admin.service.business.ride.ScanRideOrderService;
import com.njtoyo.taxi.admin.utils.Identifier;
import com.njtoyo.taxi.admin.utils.RouteDistanceCalculator;
import com.njtoyo.taxi.admin.utils.private_number.PrivateNumberClient;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.nutz.lang.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Component
public class RideServiceImpl implements RideService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private SimpleCallCustomerMapper customerMapper;
    @Autowired
    private SimpleCallMapper simpleCallMapper;
    @Autowired
    private SimpleCallRideMapper simpleCallRideMapper;
    @Autowired
    private SimpleCallRideCancellationMapper simpleCallRideCancellationMapper;
    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private RideMapper rideMapper;
    @Autowired
    private TaxiOnRideMapper taxiOnRideMapper;
    @Autowired
    private TaxiMapper taxiMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private GeoAreaMapper geoAreaMapper;

    @Autowired
    private RideOrderMapper rideOrderMapper;
    @Autowired
    private RideOrderDetailMapper rideOrderDetailMapper;

    @Autowired
    private RideCancellationMapper rideCancellationMapper;

    @Autowired
    private CancellationOrderMapper cancellationOrderMapper;

    @Autowired
    private CityMapper cityMapper;

    @Autowired
    private GeoCantonMapper geoCantonMapper;

    @Autowired
    private RideStateMapper rideStateMapper;

    @Autowired
    private DriverScoreDeductingMapper driverScoreDeductingMapper;

    @Autowired
    private CustomerCancelReasonLogMapper customerCancelReasonLogMapper;

    @Autowired
    private CustomerCancelReasonOptionMapper customerCancelReasonOptionMapper;

    @Autowired
    private RideMarkingMapper rideMarkingMapper;

    @Autowired
    private RideMarkingTagMapper rideMarkingTagMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private SuspiciousRideMapper suspiciousRideMapper;

    @Autowired
    private CouponMapper couponMapper;

    @Autowired
    private RealtimeCallMapper realtimeCallMapper;

    @Autowired
    private AppointmentCallMapper appointmentCallMapper;

    @Autowired
    private OperationRecordHelper operationRecordHelper;

    @Autowired
    private TaxiService taxiService;

    @Autowired
    private DialRecordMapper dialRecordMapper;

    @Autowired
    private CallRelevanceMapper callRelevanceMapper;

    @Autowired
    private PrimaryCachePutter primaryCachePutter;

    @Autowired
    private RideCancellationLogic rideCancellationLogic;

    @Autowired
    private RideLogic rideLogic;
    @Autowired
    private RefundService refundService;

    @Autowired
    private RideOrderLogic rideOrderLogic;

    @Autowired
    private RideLocateMapper rideLocateMapper;

    @Autowired
    private RefundLogic refundLogic;

    @Autowired
    private RideTransactionLogLogic rideTransactionLogLogic;

    @Autowired
    private RechargeLogic rechargeLogic;

    @Autowired
    private RechargeMapper rechargeMapper;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountLogic accountLogic;

    @Autowired
    private DriverLogic driverLogic;

    @Autowired
    private CancellationOrderLogic cancellationOrderLogic;

    @Autowired
    private CustomerTagMapper customerTagMapper;

    @Autowired
    private CancellationTransactionLogLogic cancellationTransactionLogLogic;
    @Autowired
    private CallEndSendMapper callEndSendMapper;
    @Autowired
    private CallPrepayOrderMapper callPrepayOrderMapper;
    @Autowired
    private CallPrepayOrderRefundLogMapper callPrepayOrderRefundLogMapper;
    @Autowired
    private CallRouteMongoRepository callRouteMongoRepository;
    @Autowired
    private RideRefundLogMapper rideRefundLogMapper;
    @Autowired
    private RideSubstitutionMapper rideSubstitutionMapper;

    @Resource
    private SimpleCallRideService simpleCallRideService;

    @Resource
    private ScanRideOrderService scanRideOrderService;

    @Resource
    private DesignatedService designatedService;

    @Autowired
    private RideRouteRepository rideRouteRepository;
    @Autowired
    private CallTypeMapper callTypeMapper;

    public RestResult<IPage<RideListPresenter>> getList(AdminUser adminUser, RideQueryWrapper query) {
        IPage<RideListPresenter> res = new Page<>();
        LambdaQueryChainWrapper<Ride> rideLambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(rideMapper)
                .in(ObjectUtil.isNotEmpty(query.getIds()), Ride::getId, query.getIds())
                .eq(ObjectUtil.isNotEmpty(query.getCategory()), Ride::getCategory, query.getCategory())
                .eq(ObjectUtil.isNotEmpty(query.getState()), Ride::getState, query.getState())
                .eq(ObjectUtil.isNotEmpty(query.getDriverId()), Ride::getDriverId, query.getDriverId())
                .eq(ObjectUtil.isNotEmpty(query.getCustomerId()), Ride::getUserId, query.getCustomerId())
                .ge(Strings.isNotBlank(query.getStartDate()), Ride::getCreatedAt, query.getStartDate())
                .eq(ObjectUtil.isNotEmpty(query.getCallType()), Ride::getCallType, query.getCallType())
                .le(Strings.isNotBlank(query.getEndDate()), Ride::getCreatedAt, query.getEndDate() + " 23:59:59");
        if (StrUtil.isNotBlank(query.getPlateNumber())) {
            List<Taxi> taxis = taxiMapper.selectLikeTaxisByPlateNumber(query.getPlateNumber());
            List<Long> taxisCollect = taxis.stream().map(Taxi::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(taxisCollect)) {
                rideLambdaQueryChainWrapper.in(Ride::getTaxiId, taxisCollect);
            } else {
                return RestResult.success(res);
            }
        }

        FilterHandler filterHandler = new FilterHandler(adminUser, query.getCantonId(), query.getCompanyId());
        switch (adminUser.getAccountType()) {
            case platform:
                rideLambdaQueryChainWrapper.eq(Objects.nonNull(query.getCantonId()), Ride::getCantonId, query.getCantonId());
                rideLambdaQueryChainWrapper.eq(Objects.nonNull(query.getCompanyId()), Ride::getCompanyId, query.getCompanyId());
                break;
            case canton:
                if (Objects.nonNull(query.getCantonId()) && filterHandler.getCantonIds().contains(query.getCantonId())) {
                    rideLambdaQueryChainWrapper.eq(Ride::getCantonId, query.getCantonId());
                } else {
                    rideLambdaQueryChainWrapper.in(Ride::getCantonId, filterHandler.getCantonIds());
                }
                if (Objects.nonNull(query.getCompanyId()) && filterHandler.getCompanyIds().contains(query.getCompanyId())) {
                    rideLambdaQueryChainWrapper.eq(Ride::getCompanyId, query.getCompanyId());
                }
                break;
            case company:
                if (Objects.nonNull(query.getCompanyId()) && filterHandler.getCompanyIds().contains(query.getCompanyId())) {
                    rideLambdaQueryChainWrapper.eq(Ride::getCompanyId, query.getCompanyId());
                } else {
                    rideLambdaQueryChainWrapper.in(Ride::getCompanyId, filterHandler.getCompanyIds());
                }
                break;
        }

        //


        // 1. 乘客搜索
        String customerSearch = query.getCustomerSearch();
        if (ObjectUtil.isNotEmpty(customerSearch)) {
            List<User> userList = new LambdaQueryChainWrapper<>(userMapper).select(User::getId).eq(this.isPhoneNum(customerSearch), User::getMobileNumber, customerSearch).like(!this.isPhoneNum(customerSearch), User::getName, customerSearch).last("limit 20").list();

            if (ObjectUtil.isEmpty(userList)) {
                return RestResult.success(res);
            } else {
                List<Long> userIds = userList.stream().map(User::getId).collect(Collectors.toList());
                rideLambdaQueryChainWrapper.in(Ride::getUserId, userIds);
            }
        }

        // 2. 司机搜索
        String driverSearch = query.getDriverSearch();
        if (ObjectUtil.isNotEmpty(driverSearch)) {
            List<Driver> driverList = new LambdaQueryChainWrapper<>(driverMapper).select(Driver::getId).eq(this.isPhoneNum(driverSearch), Driver::getMobileNumber, driverSearch).like(!this.isPhoneNum(driverSearch), Driver::getName, driverSearch).last("limit 20").list();

            if (ObjectUtil.isEmpty(driverList)) {
                return RestResult.success(res);
            } else {
                List<Long> driverIds = driverList.stream().map(Driver::getId).collect(Collectors.toList());
                rideLambdaQueryChainWrapper.in(Ride::getDriverId, driverIds);
            }
        }

        Page<Ride> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<Ride> list = rideLambdaQueryChainWrapper.in(Ride::getIsImitate, filterHandler.getIsImitates()).orderByDesc(Ride::getId).page(page);

        if (ObjectUtil.isEmpty(list.getRecords())) {
            return RestResult.success(res);
        }

        // 3. 查 taxi
        List<Long> taxiIds = list.getRecords().stream().map(Ride::getTaxiId).distinct().collect(Collectors.toList());
        Map<Long, String> taxiListMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(taxiIds)) {
            List<Taxi> taxiList = new LambdaQueryChainWrapper<>(taxiMapper).select(Taxi::getId, Taxi::getPlateNumber).in(Taxi::getId, taxiIds).list();
            taxiListMap = taxiList.stream().collect(Collectors.toMap(Taxi::getId, Taxi::getPlateNumber));
        }

        // 4. 查 driver
        List<Long> driverIds = list.getRecords().stream().map(Ride::getDriverId).distinct().collect(Collectors.toList());
        List<Driver> driverList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(driverIds)) {
            driverList = new LambdaQueryChainWrapper<>(driverMapper).select(Driver::getId, Driver::getName, Driver::getMobileNumber).in(Driver::getId, driverIds).list();
        }

        // 5. 查 company
        List<Long> companyIds = list.getRecords().stream().map(Ride::getCompanyId).distinct().collect(Collectors.toList());
        Map<Long, String> companyListMap = new HashMap<>();

        if (ObjectUtil.isNotEmpty(companyIds)) {
            companyListMap = new LambdaQueryChainWrapper<>(companyMapper).select(Company::getId, Company::getName).in(Company::getId, companyIds).list().stream().collect(Collectors.toMap(Company::getId, Company::getName));
        }

        // 6. 查 user
        List<Long> userIds = list.getRecords().stream().map(Ride::getUserId).distinct().collect(Collectors.toList());
        List<User> userList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(userIds)) {
            userList = new LambdaQueryChainWrapper<>(userMapper).select(User::getId, User::getName, User::getMobileNumber).in(User::getId, userIds).list();
        }

        // 7. 查 area
        List<Long> areaIds = list.getRecords().stream().map(Ride::getAreaId).distinct().collect(Collectors.toList());
        List<GeoArea> areaList = null;
        Map<Long, String> areaListMap = null;
        Map<Long, String> cityListMap;
        Map<Long, String> areaCityMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(areaIds)) {
            areaList = new LambdaQueryChainWrapper<>(geoAreaMapper).select(GeoArea::getId, GeoArea::getName, GeoArea::getCityId).in(GeoArea::getId, areaIds).list();
            areaListMap = areaList.stream().collect(Collectors.toMap(GeoArea::getId, GeoArea::getName));

            // 8. 查 city
            List<Long> cityIds = areaList.stream().map(GeoArea::getCityId).distinct().collect(Collectors.toList());
            if (ObjectUtil.isNotEmpty(cityIds)) {
                cityListMap = new LambdaQueryChainWrapper<>(cityMapper).select(City::getId, City::getName).in(City::getId, cityIds).list().stream().collect(Collectors.toMap(City::getId, City::getName));

                // 9. area-city
                // k:areaId,v:cityName
                for (GeoArea area : areaList) {
                    areaCityMap.put(area.getId(), cityListMap.getOrDefault(area.getCityId(), ""));
                }
            }
        }

        // 10. 查 canton
        List<Long> cantonIds = list.getRecords().stream().map(Ride::getCantonId).distinct().collect(Collectors.toList());
        Map<Long, String> cantonListMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(cantonIds)) {
            cantonListMap = new LambdaQueryChainWrapper<>(geoCantonMapper).select(GeoCanton::getId, GeoCanton::getName).in(GeoCanton::getId, cantonIds).list().stream().collect(Collectors.toMap(GeoCanton::getId, GeoCanton::getName));
        }

        // 11. 查 RideOrder
        List<Long> rideIds = list.getRecords().stream().map(Ride::getId).distinct().collect(Collectors.toList());
        List<RideOrder> rideOrderList = new ArrayList<>();
        List<RideCancellation> rideCancellationList;
        Map<Long, List<RideRefundLog>> rideRefundMapByRideId = new HashMap<>();
        List<RideListPresenter.RideCancellation> rideCancellationPresenterList = new ArrayList<>();
        List<Long> cancelIds = new ArrayList<>();
        List<CancellationOrder> cancellationOrderList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(rideIds)) {
            rideOrderList = new LambdaQueryChainWrapper<>(rideOrderMapper).select(RideOrder::getId, RideOrder::getPrepayAmount, RideOrder::getAmount, RideOrder::getRideId, RideOrder::getPresetThrough, RideOrder::getPaidThrough, RideOrder::getState, RideOrder::getRefunded).in(RideOrder::getRideId, rideIds).list();

            // 12. 查 RideCancellation
            rideCancellationList = new LambdaQueryChainWrapper<>(rideCancellationMapper).select(RideCancellation::getId, RideCancellation::getRideId, RideCancellation::getTriggerBy, RideCancellation::getResponsibility, RideCancellation::getViolate).in(RideCancellation::getRideId, rideIds).list();

            if (ObjectUtil.isNotEmpty(rideCancellationList)) {
                rideCancellationPresenterList = BeanUtil.copyToList(rideCancellationList, RideListPresenter.RideCancellation.class);

                // 13. 查 cancellation_order
                cancelIds = rideCancellationList.stream().map(RideCancellation::getId).distinct().collect(Collectors.toList());
                cancellationOrderList = new LambdaQueryChainWrapper<>(cancellationOrderMapper).in(CancellationOrder::getCancelId, cancelIds).list();

                // 为 RideCancellation 设置 CancellationOrder
                for (RideListPresenter.RideCancellation rideCancellation : rideCancellationPresenterList) {
                    if (ObjectUtil.isNotEmpty(cancellationOrderList)) {
                        for (CancellationOrder cancellationOrder : cancellationOrderList) {
                            if (cancellationOrder.getCancelId().equals(rideCancellation.getId())) {
                                rideCancellation.setCancellationOrder(BeanUtil.copyProperties(cancellationOrder, RideListPresenter.CancellationOrder.class));
                            }
                        }
                    }
                }
            }

            List<RideRefundLog> rideRefundLogList = rideRefundLogMapper.selectList(Wrappers.<RideRefundLog>lambdaQuery()
                    .in(RideRefundLog::getState, Arrays.asList(0, 2))
                    .in(RideRefundLog::getRideId, rideIds));
            rideRefundMapByRideId = rideRefundLogList.stream().collect(Collectors.groupingBy(RideRefundLog::getRideId));
        }

        List<CallType> callTypes = callTypeMapper.selectList(null);
        Map<Long, String> callTypeMap = new HashMap<>();
        if (CollUtil.isNotEmpty(callTypes)) {
            callTypeMap = callTypes.stream().collect(Collectors.toMap(CallType::getId, CallType::getName));
        }

        Map<Long, String> finalTaxiListMap = taxiListMap;
        List<Driver> finalDriverList = driverList;
        Map<Long, String> finalCompanyListMap = companyListMap;
        List<User> finalUserList = userList;
        Map<Long, String> finalAreaListMap = areaListMap;
        List<GeoArea> finalAreaList = areaList;
        Map<Long, String> finalCantonListMap = cantonListMap;
        List<RideOrder> finalRideOrderList = rideOrderList;
        Map<Long, List<RideRefundLog>> rideRefundMapByRideIdNew = rideRefundMapByRideId;
        List<RideListPresenter.RideCancellation> finalRideCancellationPresenterList = rideCancellationPresenterList;
        Map<Long, String> newCallTypeMap = callTypeMap;


        res = list.convert(ride -> {
            RideListPresenter item = BeanUtil.copyProperties(ride, RideListPresenter.class);
            item.setCallId(ride.getRefId());


            if (Objects.nonNull(ride.getTaxiId()) && ObjectUtil.isNotEmpty(finalTaxiListMap)) {
                RideListPresenter.Taxi taxi = new RideListPresenter.Taxi();
                taxi.setId(ride.getTaxiId());
                taxi.setPlateNumber(finalTaxiListMap.getOrDefault(ride.getTaxiId(), ""));
                item.setTaxi(taxi);
            }

            if (Objects.nonNull(ride.getDriverId()) && ObjectUtil.isNotEmpty(finalDriverList)) {
                RideListPresenter.Driver driver = new RideListPresenter.Driver();
                driver.setId(ride.getDriverId());
                for (Driver rideDriver : finalDriverList) {
                    if (ride.getDriverId().equals(rideDriver.getId())) {
                        driver.setName(rideDriver.getName());
                        driver.setMobileNumber(rideDriver.getMobileNumber());
                        break;
                    }
                }
                item.setDriver(driver);
            }

            if (Objects.nonNull(ride.getCompanyId()) && ObjectUtil.isNotEmpty(finalCompanyListMap)) {
                RideListPresenter.Company company = new RideListPresenter.Company();
                company.setId(ride.getCompanyId());
                company.setName(finalCompanyListMap.getOrDefault(ride.getCompanyId(), ""));
                item.setCompany(company);
            }

            if (Objects.nonNull(ride.getUserId()) && ObjectUtil.isNotEmpty(finalUserList)) {
                RideListPresenter.User user = new RideListPresenter.User();
                user.setId(ride.getUserId());
                for (User rideUser : finalUserList) {
                    if (ride.getUserId().equals(rideUser.getId())) {
                        user.setName(rideUser.getName());
                        user.setMobileNumber(rideUser.getMobileNumber());
                        break;
                    }
                }
                item.setUser(user);
            }

            if (Objects.nonNull(ride.getAreaId()) && ObjectUtil.isNotEmpty(finalAreaListMap)) {
                RideListPresenter.Area area = new RideListPresenter.Area();
                area.setId(ride.getAreaId());
                area.setName(finalAreaListMap.getOrDefault(ride.getAreaId(), ""));
                item.setArea(area);

                RideListPresenter.City city = new RideListPresenter.City();
                for (GeoArea areaItem : finalAreaList) {
                    if (ride.getAreaId().equals(areaItem.getId())) {
                        city.setId(areaItem.getCityId());
                        city.setName(areaCityMap.getOrDefault(ride.getAreaId(), ""));
                        item.setCity(city);
                        break;
                    }
                }
            }

            if (Objects.nonNull(ride.getCantonId()) && ObjectUtil.isNotEmpty(finalCantonListMap)) {
                RideListPresenter.Canton canton = new RideListPresenter.Canton();
                canton.setId(ride.getCantonId());
                canton.setName(finalCantonListMap.getOrDefault(ride.getCantonId(), ""));
                item.setCanton(canton);
            }

            // RideOrder
            if (ObjectUtil.isNotEmpty(finalRideOrderList)) {
                for (RideOrder order : finalRideOrderList) {
                    if (ride.getId().equals(order.getRideId())) {
                        item.setRideOrder(BeanUtil.copyProperties(order, RideListPresenter.RideOrder.class));
                        //判断是否为部分退款
                        List<RideRefundLog> refundLogs = rideRefundMapByRideIdNew.get(ride.getId());
                        if (ObjectUtil.isNotEmpty(refundLogs)) {
                            BigDecimal refundAmount = refundLogs.stream().filter(x -> x.getState() != 1).map(RideRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                            if (!order.getRefunded() && refundAmount.compareTo(BigDecimal.ZERO) > 0) {
                                item.setPartialRefund(true);
                            }
                        }
                        break;
                    }
                }
            }

            // RideCancellation
            if (ObjectUtil.isNotEmpty(finalRideCancellationPresenterList)) {
                for (RideListPresenter.RideCancellation rideCancellationItem : finalRideCancellationPresenterList) {
                    if (ride.getId().equals(rideCancellationItem.getRideId())) {
                        item.setRideCancellation(BeanUtil.copyProperties(rideCancellationItem, RideListPresenter.RideCancellation.class));
                        break;
                    }
                }
            }

            if (ride.getCategory() == RideCategory.realtime) {
                RealtimeCall realtimeCall = realtimeCallMapper.selectById(ride.getRefId());
                if (ObjectUtil.isNotNull(realtimeCall)) {
                    item.setNeedPrepay(realtimeCall.getNeedPrepay());
                    String callName = newCallTypeMap.get(realtimeCall.getCallType());
                    item.setCallType(StrUtil.isBlank(callName) ? "-" : callName);
                }
            } else if (ride.getCategory() == RideCategory.appointment) {
                AppointmentCall appointmentCall = appointmentCallMapper.selectById(ride.getRefId());
                if (ObjectUtil.isNotNull(appointmentCall)) {
                    item.setNeedPrepay(appointmentCall.getNeedPrepay());
                }
            }

            return item;
        });

        return RestResult.success(res);
    }

    private Boolean isPhoneNum(String content) {
        return ReUtil.isMatch("^1[0-9]\\d{9}$", content);
    }

    @Override
    public RestResult<RideDetailPresenter> getRideDetail(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        RideDetailPresenter res = BeanUtil.copyProperties(ride, RideDetailPresenter.class);
        // taxi
        if (Objects.nonNull(ride.getTaxiId())) {
            Taxi taxi = new LambdaQueryChainWrapper<>(taxiMapper).select(Taxi::getId, Taxi::getPlateNumber).eq(Taxi::getId, ride.getTaxiId()).one();
            if (Objects.nonNull(taxi)) {
                res.setTaxi(BeanUtil.copyProperties(taxi, RideDetailPresenter.Taxi.class));
            }
        }

        // driver
        if (Objects.nonNull(ride.getDriverId())) {
            Driver driver = new LambdaQueryChainWrapper<>(driverMapper).select(Driver::getId, Driver::getName, Driver::getMobileNumber).eq(Driver::getId, ride.getDriverId()).one();
            if (Objects.nonNull(driver)) {
                res.setDriver(BeanUtil.copyProperties(driver, RideDetailPresenter.Driver.class));
            }
        }

        // company
        if (Objects.nonNull(ride.getCompanyId())) {
            Company company = new LambdaQueryChainWrapper<>(companyMapper).select(Company::getId, Company::getName).eq(Company::getId, ride.getCompanyId()).one();
            if (Objects.nonNull(company)) {
                res.setCompany(BeanUtil.copyProperties(company, RideDetailPresenter.Company.class));
            }
        }

        // user
        if (Objects.nonNull(ride.getUserId())) {
            User user = new LambdaQueryChainWrapper<>(userMapper).select(User::getId, User::getName, User::getMobileNumber).eq(User::getId, ride.getUserId()).one();
            if (Objects.nonNull(user)) {
                res.setUser(BeanUtil.copyProperties(user, RideDetailPresenter.User.class));
            }
        }

        // area
        if (Objects.nonNull(ride.getAreaId())) {
            GeoArea area = new LambdaQueryChainWrapper<>(geoAreaMapper).select(GeoArea::getId, GeoArea::getName, GeoArea::getCityId).eq(GeoArea::getId, ride.getAreaId()).one();
            if (Objects.nonNull(area)) {
                res.setArea(BeanUtil.copyProperties(area, RideDetailPresenter.Area.class));

                // city
                if (Objects.nonNull(area.getCityId())) {
                    City city = new LambdaQueryChainWrapper<>(cityMapper).select(City::getId, City::getName).eq(City::getId, area.getCityId()).one();
                    if (Objects.nonNull(city)) {
                        res.setCity(BeanUtil.copyProperties(city, RideDetailPresenter.City.class));
                    }
                }
            }
        }

        // canton
        if (Objects.nonNull(ride.getCantonId())) {
            GeoCanton canton = new LambdaQueryChainWrapper<>(geoCantonMapper).select(GeoCanton::getId, GeoCanton::getName).eq(GeoCanton::getId, ride.getCantonId()).one();
            if (Objects.nonNull(canton)) {
                res.setCanton(BeanUtil.copyProperties(canton, RideDetailPresenter.Canton.class));
            }
        }

        // ride_order
        RideOrder ride_order = new LambdaQueryChainWrapper<>(rideOrderMapper).in(RideOrder::getRideId, id).one();

        if (Objects.nonNull(ride_order)) {
            RideDetailPresenter.RideOrder rideOrder = BeanUtil.copyProperties(ride_order, RideDetailPresenter.RideOrder.class);
            // coupon
            if (Objects.nonNull(ride_order.getCouponId())) {
                Coupon coupon = new LambdaQueryChainWrapper<>(couponMapper).select(Coupon::getId, Coupon::getCategory, Coupon::getDigit, Coupon::getLimitation).eq(Coupon::getId, ride_order.getCouponId()).one();
                rideOrder.setCoupon(BeanUtil.copyProperties(coupon, RideDetailPresenter.Coupon.class));
                rideOrder.setHasOnline(ride_order.getHasOnline());
            }
            // ride_order_detail
            RideOrderDetail rideOrderDetail = rideOrderDetailMapper.selectOne(Wrappers.<RideOrderDetail>lambdaQuery().eq(RideOrderDetail::getRideId, id));
            if (ObjectUtil.isNotNull(rideOrderDetail)) {
                rideOrder.setTaxiFee(ObjectUtil.isNotEmpty(rideOrderDetail.getTaxiFee()) ? rideOrderDetail.getTaxiFee() : new BigDecimal(0));
                rideOrder.setTollFee(ObjectUtil.isNotEmpty(rideOrderDetail.getTollFee()) ? rideOrderDetail.getTollFee() : new BigDecimal(0));
                rideOrder.setOtherFee(ObjectUtil.isNotEmpty(rideOrderDetail.getOtherFee()) ? rideOrderDetail.getOtherFee() : new BigDecimal(0));
                rideOrder.setHolidayFee(ObjectUtil.isNotEmpty(rideOrderDetail.getHolidayFee()) ? rideOrderDetail.getHolidayFee() : new BigDecimal(0));
                rideOrder.setBadWeatherFee(ObjectUtil.isNotEmpty(rideOrderDetail.getBadWeatherFee()) ? rideOrderDetail.getBadWeatherFee() : new BigDecimal(0));
                rideOrder.setEmptyBackFee(ObjectUtil.isNotEmpty(rideOrderDetail.getEmptyBackFee()) ? rideOrderDetail.getEmptyBackFee() : new BigDecimal(0));
                rideOrder.setWaitingFee(ObjectUtil.isNotEmpty(rideOrderDetail.getWaitingFee()) ? rideOrderDetail.getWaitingFee() : new BigDecimal(0));
                rideOrder.setExceedTimeFee(ObjectUtil.isNotEmpty(rideOrderDetail.getExceedTimeFee()) ? rideOrderDetail.getExceedTimeFee() : new BigDecimal(0));
                rideOrder.setExceedMileageFee(ObjectUtil.isNotEmpty(rideOrderDetail.getExceedMileageFee()) ? rideOrderDetail.getExceedMileageFee() : new BigDecimal(0));
                rideOrder.setStartingFee(ObjectUtil.isNotEmpty(rideOrderDetail.getStartingFee()) ? rideOrderDetail.getStartingFee() : new BigDecimal(0));
                rideOrder.setDriverCommission(ObjectUtil.isNotEmpty(rideOrderDetail.getDriverCommission()) ? rideOrderDetail.getDriverCommission() : new BigDecimal(0));
            } else {
                rideOrder.setTaxiFee(new BigDecimal(0));
                rideOrder.setTollFee(new BigDecimal(0));
                rideOrder.setOtherFee(new BigDecimal(0));
                rideOrder.setHolidayFee(new BigDecimal(0));
                rideOrder.setBadWeatherFee(new BigDecimal(0));
                rideOrder.setEmptyBackFee(new BigDecimal(0));
                rideOrder.setWaitingFee(new BigDecimal(0));
                rideOrder.setExceedMileageFee(new BigDecimal(0));
                rideOrder.setExceedTimeFee(new BigDecimal(0));
                rideOrder.setStartingFee(new BigDecimal(0));
            }
            Boolean refund = ObjectUtil.isNotNull(ride_order.getRefunded()) ? ride_order.getRefunded() : false;
            if (!refund) {
                List<RideRefundLog> refundLogs = rideRefundLogMapper.selectList(Wrappers.<RideRefundLog>lambdaQuery()
                        .in(RideRefundLog::getState, Arrays.asList(0, 2))
                        .eq(RideRefundLog::getRideId, id));
                BigDecimal refundAmount = (refundLogs == null)
                        ? BigDecimal.ZERO
                        : refundLogs.stream()
                        .filter(Objects::nonNull)
                        .filter(x -> x.getState() != 1)
                        .map(RideRefundLog::getRefundAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                if (refundAmount.compareTo(BigDecimal.ZERO) > 0) {
                    rideOrder.setRefundType("part");
                } else {
                    rideOrder.setRefundType("none");
                }
            }

            res.setRideOrder(rideOrder);
        }


        // ride_state
        List<RideState> rideStateList = new LambdaQueryChainWrapper<>(rideStateMapper).eq(RideState::getRideId, ride.getId()).list();
        if (ObjectUtil.isNotEmpty(rideStateList)) {
            List<RideDetailPresenter.RideStateLog> rideStateLogList = new ArrayList<>();
            rideStateList.forEach(i -> {
                RideDetailPresenter.RideStateLog rideStateLog = BeanUtil.copyProperties(i, RideDetailPresenter.RideStateLog.class);
                rideStateLogList.add(rideStateLog);
            });

            res.setRideStateLog(rideStateLogList);
        }

        // ride_cancellation
        RideCancellation ride_cancellation = new LambdaQueryChainWrapper<>(rideCancellationMapper).select(RideCancellation::getId, RideCancellation::getPenalty, RideCancellation::getRideId, RideCancellation::getTriggerBy, RideCancellation::getResponsibility, RideCancellation::getViolate, RideCancellation::getCreatedAt, RideCancellation::getUpdatedAt).eq(RideCancellation::getRideId, ride.getId()).one();

        if (Objects.nonNull(ride_cancellation)) {
            RideDetailPresenter.RideCancellation rideCancellation = BeanUtil.copyProperties(ride_cancellation, RideDetailPresenter.RideCancellation.class);

            CancellationOrder cancellationOrder = new LambdaQueryChainWrapper<>(cancellationOrderMapper).eq(CancellationOrder::getCancelId, ride_cancellation.getId()).one();

            // cancellation_order
            if (Objects.nonNull(cancellationOrder)) {
                RideDetailPresenter.CancellationOrder cancellationOrderSub = BeanUtil.copyProperties(cancellationOrder, RideDetailPresenter.CancellationOrder.class);
                rideCancellation.setCancellationOrder(cancellationOrderSub);
            }

            // driver_score_deduct
            DriverScoreDeducting driverScoreDeducting = new LambdaQueryChainWrapper<>(driverScoreDeductingMapper).select(DriverScoreDeducting::getId, DriverScoreDeducting::getDeduction, DriverScoreDeducting::getStartedAt, DriverScoreDeducting::getEndedAt).eq(DriverScoreDeducting::getReferenceId, ride_cancellation.getId()).one();

            if (Objects.nonNull(driverScoreDeducting)) {
                RideDetailPresenter.DriverScoreDeduct driverScoreDeductingSub = BeanUtil.copyProperties(driverScoreDeducting, RideDetailPresenter.DriverScoreDeduct.class);
                rideCancellation.setDriverScoreDeduct(driverScoreDeductingSub);
            }

            res.setRideCancellation(rideCancellation);

            // customer_cancel_reason_log
            CustomerCancelReasonLog customer_cancel_reason_log = new LambdaQueryChainWrapper<>(customerCancelReasonLogMapper).select(CustomerCancelReasonLog::getId, CustomerCancelReasonLog::getReason, CustomerCancelReasonLog::getCreatedAt, CustomerCancelReasonLog::getUpdatedAt, CustomerCancelReasonLog::getRefId).eq(CustomerCancelReasonLog::getRideId, ride.getId()).one();

            if (Objects.nonNull(customer_cancel_reason_log)) {
                RideDetailPresenter.CustomerCancelReasonLog customerCancelReasonLog = BeanUtil.copyProperties(customer_cancel_reason_log, RideDetailPresenter.CustomerCancelReasonLog.class);
                // reasonOption
                CustomerCancelReasonOption customerCancelReasonOption = new LambdaQueryChainWrapper<>(customerCancelReasonOptionMapper).select(CustomerCancelReasonOption::getId, CustomerCancelReasonOption::getCategory, CustomerCancelReasonOption::getReason).eq(CustomerCancelReasonOption::getId, customer_cancel_reason_log.getRefId()).one();
                if (Objects.nonNull(customerCancelReasonOption)) {
                    RideDetailPresenter.ReasonOption customerCancelReasonOptionSub = BeanUtil.copyProperties(customerCancelReasonOption, RideDetailPresenter.ReasonOption.class);
                    customerCancelReasonLog.setReasonOption(customerCancelReasonOptionSub);
                }

                res.setCustomerCancelReasonLog(customerCancelReasonLog);
            }
        }

        // ride_marking
        RideMarking ride_marking = new LambdaQueryChainWrapper<>(rideMarkingMapper).select(RideMarking::getId, RideMarking::getScore, RideMarking::getComment, RideMarking::getCreatedAt).eq(RideMarking::getRideId, ride.getId()).one();
        if (Objects.nonNull(ride_marking)) {
            // 设置score，category
            RideDetailPresenter.RideMarking rideMarking = BeanUtil.copyProperties(ride_marking, RideDetailPresenter.RideMarking.class);

            // ride_marking_tag
            List<RideMarkingTag> rideMarkingTagList = new LambdaQueryChainWrapper<>(rideMarkingTagMapper).eq(RideMarkingTag::getMarkingId, ride_marking.getId()).list();

            // 获取tag
            if (ObjectUtil.isNotEmpty(rideMarkingTagList)) {
                List<Long> tagIds = rideMarkingTagList.stream().map(RideMarkingTag::getTagId).collect(Collectors.toList());
                // 根据tagIds查询tag
                List<Tag> tagList = new LambdaQueryChainWrapper<>(tagMapper).in(Tag::getId, tagIds).list();
                if (ObjectUtil.isNotEmpty(tagList)) {
                    List<RideDetailPresenter.RideMarkingTag> rideMarkingTags = new ArrayList<>();

                    for (Tag tag : tagList) {
                        RideDetailPresenter.RideMarkingTag rideMarkingTagSub = new RideDetailPresenter.RideMarkingTag();
                        rideMarkingTagSub.setId(tag.getId());
                        rideMarkingTagSub.setTitle(tag.getTitle());
                        rideMarkingTagSub.setCategory(tag.getCategory());
                        rideMarkingTags.add(rideMarkingTagSub);
                    }

                    rideMarking.setRideMarkingTag(rideMarkingTags);
                }
            }
            res.setRideMarking(rideMarking);
        }

        // suspicious_ride
        SuspiciousRide suspiciousRide = new LambdaQueryChainWrapper<>(suspiciousRideMapper).eq(SuspiciousRide::getRideId, ride.getId()).one();
        if (Objects.nonNull(suspiciousRide)) {
            res.setSuspiciousRide(suspiciousRide);
        }

        // callInfo
        if (Objects.nonNull(ride.getCategory())) {
            RideDetailPresenter.CallInfo callInfo = new RideDetailPresenter.CallInfo();
            callInfo.setType(ride.getCategory());
            // realtime_call
            if (ride.getCategory().equals(RideCategory.realtime)) {
                RealtimeCall realtimeCall = new LambdaQueryChainWrapper<>(realtimeCallMapper).eq(RealtimeCall::getId, ride.getRefId()).one();
                if (Objects.nonNull(realtimeCall)) {
                    callInfo.setRealtime(BeanUtil.copyProperties(realtimeCall, RideDetailPresenter.RealtimeCall.class));
                    res.setNeedPrepay(realtimeCall.getNeedPrepay());
                    if (ObjectUtil.isNotNull(realtimeCall.getNeedPrepay()) && realtimeCall.getNeedPrepay()) {
                        CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectOne(Wrappers.<CallPrepayOrder>lambdaQuery().eq(CallPrepayOrder::getCallId, realtimeCall.getId()));
                        if (ObjectUtil.isNotNull(callPrepayOrder)) {
                            res.setPrepayAmount(callPrepayOrder.getAmount());
                            res.setPrepayState(callPrepayOrder.getState());
                            //退预付
                            List<CallPrepayOrderRefundLog> callPrepayOrderRefundLogs = callPrepayOrderRefundLogMapper.selectList(Wrappers.<CallPrepayOrderRefundLog>lambdaQuery().eq(CallPrepayOrderRefundLog::getIsSuccess, true).eq(CallPrepayOrderRefundLog::getOrderId, callPrepayOrder.getId()));
                            if (CollUtil.isNotEmpty(callPrepayOrderRefundLogs)) {
                                CallPrepayOrderRefundLog refundLog = callPrepayOrderRefundLogs.get(callPrepayOrderRefundLogs.size() - 1);
                                res.setPrepayRefundTime(DateUtil.formatDateTime(refundLog.getCreatedAt()));
                                BigDecimal refundAmount = callPrepayOrderRefundLogs.stream().map(CallPrepayOrderRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                                res.setPrepayRefundAmount(Convert.toStr(refundAmount));

                            }
                        }
                    }
                }
            }

            // appointment_call
            if (ride.getCategory().equals(RideCategory.appointment)) {
                AppointmentCall appointmentCall = new LambdaQueryChainWrapper<>(appointmentCallMapper).eq(AppointmentCall::getId, ride.getRefId()).one();
                res.setNeedPrepay(appointmentCall.getNeedPrepay());
                if (Objects.nonNull(appointmentCall)) {
                    callInfo.setAppointment(BeanUtil.copyProperties(appointmentCall, RideDetailPresenter.AppointmentCall.class));
                }
                if (ObjectUtil.isNotNull(appointmentCall.getNeedPrepay()) && appointmentCall.getNeedPrepay()) {
                    CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectOne(Wrappers.<CallPrepayOrder>lambdaQuery().eq(CallPrepayOrder::getCallId, appointmentCall.getId()));
                    if (ObjectUtil.isNotNull(callPrepayOrder)) {
                        res.setPrepayAmount(callPrepayOrder.getAmount());
                        res.setPrepayState(callPrepayOrder.getState());
                        //退预付
                        List<CallPrepayOrderRefundLog> callPrepayOrderRefundLogs = callPrepayOrderRefundLogMapper.selectList(Wrappers.<CallPrepayOrderRefundLog>lambdaQuery().eq(CallPrepayOrderRefundLog::getIsSuccess, true).eq(CallPrepayOrderRefundLog::getOrderId, callPrepayOrder.getId()));
                        if (CollUtil.isNotEmpty(callPrepayOrderRefundLogs)) {
                            CallPrepayOrderRefundLog refundLog = callPrepayOrderRefundLogs.get(callPrepayOrderRefundLogs.size() - 1);
                            res.setPrepayRefundTime(DateUtil.formatDateTime(refundLog.getCreatedAt()));
                            BigDecimal refundAmount = callPrepayOrderRefundLogs.stream().map(CallPrepayOrderRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                            res.setPrepayRefundAmount(Convert.toStr(refundAmount));

                        }
                    }
                }
            }

            res.setCallInfo(callInfo);
        }
        if (ride.getIsPassengerSubstitution()) {
            //代叫订单
            RideSubstitution rs = rideSubstitutionMapper.selectOne(new QueryWrapper<RideSubstitution>().lambda().eq(RideSubstitution::getRideId, id));
            res.setRideSubstitution(rs);
        }
        return RestResult.success(res);
    }

    @Override
    public RestResult<Boolean> suspiciousConfirm(Long id, SuspiciousConfirmWrapper wrapper) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // suspicious_ride
        SuspiciousRide suspiciousRide = new LambdaQueryChainWrapper<>(suspiciousRideMapper).eq(SuspiciousRide::getRideId, id).one();
        if (Objects.isNull(suspiciousRide)) {
            return RestResult.failed("此行程不存在可疑信息");
        }

        if (suspiciousRide.getIsCheck()) {
            return RestResult.failed("行程异常已确认过了");
        }

        boolean res = new LambdaUpdateChainWrapper<>(suspiciousRideMapper).eq(SuspiciousRide::getId, suspiciousRide.getId()).set(SuspiciousRide::getIsCheck, true).set(SuspiciousRide::getAdminJudgment, wrapper.getAdminJudgment()).set(SuspiciousRide::getUpdatedAt, new Date()).update();

        operationRecordHelper.addBusinessLog(String.format("确认并处理行程异常信息,行程ID [%d]", id));

        return RestResult.success(res);
    }

    /**
     * 将行程订单的线上付款方式改为线下支付
     */
    @Override
    @DSTransactional
    public RestResult<Boolean> onlineOrderSetOffline(AdminUser adminUser, Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断ride是否处于完成待付款状态
        if (!RideStateState.ended.equals(ride.getState())) {
            return RestResult.failed("此行程不处于完成待付款状态");
        }

        // 判断行程是否有未付款的订单
        RideOrder rideOrder = rideOrderLogic.getUnpaidOrderByRideId(id);
        if (Objects.isNull(rideOrder)) {
            return RestResult.failed("此行程没有未付款行程订单");
        }

        // 判断行程订单付款方式是否为线下付款
        if (RideOrderPaidThrough.cash.equals(rideOrder.getPresetThrough())) {
            return RestResult.failed("此行程已经是线下支付方式");
        }

        taxiOnRideMapper.delete(Wrappers.<TaxiOnRide>lambdaQuery().eq(TaxiOnRide::getRideId, ride.getId()));
        RideCancellation cancellation = rideCancellationMapper.selectOne(Wrappers.<RideCancellation>lambdaQuery().eq(RideCancellation::getRideId, ride.getId()));
        rideCancellationMapper.delete(Wrappers.<RideCancellation>lambdaQuery().eq(RideCancellation::getRideId, ride.getId()));
        if (ObjectUtil.isNotNull(cancellation)) {
            cancellationOrderMapper.delete(Wrappers.<CancellationOrder>lambdaQuery().eq(CancellationOrder::getCancelId, cancellation.getId()));
        }

        boolean updateRideState = rideLogic.updateState(id, RideStateState.completed);

        boolean updateRideOrder = rideOrderLogic.onlineOrderSetOffline(id, rideOrder);

        // 通知服务端
        taxiService.unboundNumber(id);

        Driver driver = new LambdaQueryChainWrapper<>(driverMapper).select(Driver::getId).eq(Driver::getId, ride.getDriverId()).one();

        //解绑隐私通话
        List<CallRelevance> callRelevances = callRelevanceMapper.selectList(Wrappers.<CallRelevance>lambdaQuery().eq(CallRelevance::getRideId, ride.getId()));
        for (CallRelevance callRelevance : callRelevances) {
            boolean unbindResult = PrivateNumberClient.unbindMobileNumber(callRelevance.getSubscriptionId());
            if (unbindResult) {
                callRelevance.setIsEffective(false);
                callRelevanceMapper.updateById(callRelevance);
            }
        }

        // 清理司机的缓存，记录操作日志
        primaryCachePutter.deleteDriverTodayIncome(driver.getId());
        operationRecordHelper.addBusinessLog(String.format("将行程订单的线上付款方式改为线下支付,行程ID [%d]", id));

        //退预付
        CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectByRideIdAndCategory(id, 0);
        if (ObjectUtil.isNotNull(callPrepayOrder) && callPrepayOrder.getState() == 2 && !callPrepayOrder.getIsRefund()) {
            Boolean refundResult = refundService.refund(ride.getRefId(), ride.getId(), ride.getCategory(),
                    "order", null, "ALL", "线上改线下", adminUser.getName());
        }
        return RestResult.success(updateRideState && updateRideOrder);
    }

    /**
     * 将行程订单的线下付款方式改为线上支付
     */
    @Override
    @DSTransactional
    public RestResult<Boolean> offlineOrderSetOnline(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断行程订单是否符合线下改线上支付规则
        List<RideStateState> checkRideStateList = Arrays.asList(RideStateState.ended, RideStateState.completed, RideStateState.marked);
        RideOrder rideOrder = rideOrderLogic.getOneRideOrderByRideId(id);

        if (!checkRideStateList.contains(ride.getState()) || Objects.isNull(rideOrder) || Objects.isNull(rideOrder.getPresetThrough()) || !RideOrderPaidThrough.cash.equals(rideOrder.getPresetThrough())) {
            return RestResult.failed("此行程订单无法改为线上付款方式");
        }

        boolean updateRideState = rideLogic.updateState(id, RideStateState.ended);

        boolean updateRideOrder = rideOrderLogic.offlineOrderSetOnline(id);

        // 若存在评论 ride_marking
        RideMarking ride_marking = new LambdaQueryChainWrapper<>(rideMarkingMapper).select(RideMarking::getId).eq(RideMarking::getRideId, id).one();
        if (Objects.nonNull(ride_marking)) {
            LambdaQueryWrapper<RideMarkingTag> tagWrapper = new LambdaQueryWrapper<>();
            tagWrapper.eq(RideMarkingTag::getMarkingId, ride_marking.getId());
            rideMarkingTagMapper.delete(tagWrapper);
        }

        operationRecordHelper.addBusinessLog(String.format("将行程订单的线下付款方式改为线上支付,行程ID [%d]", id));

        return RestResult.success(updateRideState && updateRideOrder);
    }

    @Override
    public RestResult<List<RideDialListPresenter>> getDialList(AdminUser adminUser, Long id) {
        Ride ride = rideMapper.selectById(id);
        if (Objects.isNull(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        List<Long> ids = callRelevanceMapper.getIdsByRideId(id);
        if (ids.isEmpty()) {
            return RestResult.failed("暂无行程通话记录");
        }

        QueryWrapper<DialRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("call_relevance_id", ids).orderByDesc("id");
        List<DialRecord> dialRecords = dialRecordMapper.selectList(queryWrapper);
        if (dialRecords.isEmpty()) {
            return RestResult.failed("暂无行程通话记录");
        }
        List<RideDialListPresenter> res = CopyUtil.copyList(dialRecords, RideDialListPresenter.class);

        return RestResult.success(res);
    }

    /**
     * 有责改无责(司机有责)
     */
    @Override
    @DSTransactional
    public RestResult<Boolean> driverCancellationResponsibilityEliminate(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断该行程是否存在司机的有责取消行为
        RideCancellation rideCancellation = new LambdaQueryChainWrapper<>(rideCancellationMapper).select(RideCancellation::getId, RideCancellation::getViolate, RideCancellation::getResponsibility).eq(RideCancellation::getRideId, id).one();

        if (Objects.isNull(rideCancellation) || rideCancellation.getViolate().equals(RideCancellationViolate.none) || !rideCancellation.getResponsibility().equals(RideCancellationResponsibility.driver)) {
            return RestResult.failed("此行程没有司机有责取消行为");
        }

        boolean updateRideCancellation = rideCancellationLogic.cancellationResponsibilityEliminate(rideCancellation.getId());

        boolean updateRide = rideLogic.cancellationResponsibilityEliminate(id);

        // 记录司机信息
        if (Objects.isNull(ride.getDriverId())) {
            return RestResult.failed("此行程没有司机");
        }

        Driver driver = new LambdaQueryChainWrapper<>(driverMapper).eq(Driver::getId, ride.getDriverId()).one();
        log.info(String.format("管理员将司机有责改无责，司机信息 [%s]", driver));

        // 把扣掉的分数加回去
        // 获取扣掉的分数
        DriverScoreDeducting deleteScore = new LambdaQueryChainWrapper<>(driverScoreDeductingMapper).select(DriverScoreDeducting::getDeduction).eq(DriverScoreDeducting::getReferenceId, rideCancellation.getId()).one();
        log.info(String.format("管理员将司机有责改无责，扣掉的分数 [%d]", deleteScore.getDeduction()));

        // 获取司机当前分数
        log.info(String.format("管理员将司机有责改无责，司机当前分数 [%f]", driver.getMarkScore()));

        BigDecimal addScore = NumberUtil.add(driver.getMarkScore(), new BigDecimal(deleteScore.getDeduction()));
        BigDecimal updateScore = addScore.compareTo(new BigDecimal(100)) < 0 ? addScore : new BigDecimal(100);

        // 更新司机分数
        boolean updateDriver = new LambdaUpdateChainWrapper<>(driverMapper).eq(Driver::getId, ride.getDriverId()).set(Driver::getMarkScore, updateScore).set(Driver::getUpdatedAt, new Date()).update();
        log.info(String.format("管理员将司机有责改无责，司机更新后的分数 [%f]", updateScore));

        LambdaQueryWrapper<DriverScoreDeducting> driverScoreDeducting = new LambdaQueryWrapper<>();
        driverScoreDeducting.eq(DriverScoreDeducting::getReferenceId, rideCancellation.getId());
        driverScoreDeductingMapper.delete(driverScoreDeducting);

        // 清理司机的缓存，记录操作日志
        primaryCachePutter.deleteDriverCacheById(driver.getId());
        primaryCachePutter.deleteDriverTodayIncome(driver.getId());

        operationRecordHelper.addBusinessLog(String.format("管理员将司机有责改无责，行程id [%d]", ride.getId()));

        return RestResult.success(true);
    }

    @Override
    public RestResult<Boolean> updateState(Long id, UpdateStateWrapper wrapper) {
        List<RideStateState> allowState = Arrays.asList(RideStateState.started, RideStateState.ended);
        if (!allowState.contains(wrapper.getState())) {
            return RestResult.failed("行程状态 参数错误");
        }

        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        if (RideStateState.pickuping.equals(ride.getState()) || (RideStateState.started.equals(ride.getState()) && RideStateState.ended.equals(wrapper.getState()))) {
            boolean update = rideLogic.updateStateTrans(id, wrapper.getState());
            if (update) {
                String stateStr = null;
                if (RideStateState.started.equals(wrapper.getState())) {
                    stateStr = "started";
                } else if (RideStateState.ended.equals(wrapper.getState())) {
                    stateStr = "ended";
                }

                if (ObjectUtil.isNotEmpty(stateStr)) {
                    // 通知服务端
                    taxiService.updateRideStateNotice(id, stateStr);
                }

                operationRecordHelper.addBusinessLog(String.format("行程id [%d] 状态改为 %s", id, stateStr));
                return RestResult.success(true);
            }
            return RestResult.failed("操作失败");
        } else {
            return RestResult.failed("修改失败 不允许这样修改状态");
        }
    }

    @Override
    @DSTransactional
    public RestResult<Boolean> customerCancellationResponsibilityEliminate(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断该行程是否存在乘客的有责取消行为
        RideCancellation rideCancellation = rideLogic.getCustomerForceCancellation(id);

        if (Objects.isNull(rideCancellation) || rideCancellation.getViolate().equals(RideCancellationViolate.none) || !rideCancellation.getResponsibility().equals(RideCancellationResponsibility.customer)) {
            return RestResult.failed("此行程没有乘客有责取消行为");
        }

        // 查 cancellation_order
        CancellationOrder cancellationOrder = new LambdaQueryChainWrapper<>(cancellationOrderMapper).in(CancellationOrder::getCancelId, rideCancellation.getId()).one();

        // 判断有没有空驶费订单，没有则操作失败
        if (Objects.isNull(cancellationOrder)) {
            return RestResult.failed("数据异常，乘客有责取消缺失空驶费订单");
        }

        // 判断有责取消订单是否已完成支付，如果完成，应该调用[有责取消退款：refund_cancellation_order]接口
        if (RideOrderState.done.equals(cancellationOrder.getState())) {
            return RestResult.failed("操作失败，有责取消订单已完成支付");
        } else {
            // 罚金订单未支付
            // 管理员将未支付的有责取消改为无责（直接删除罚金订单）
            cancellationOrderMapper.deleteById(cancellationOrder.getId());

            // 修改cancellation.violate=none,resp=admin
            boolean updateRideCancellation = rideCancellationLogic.cancellationResponsibilityEliminate(rideCancellation.getId());

            // 修改ride.state=cancel
            boolean updateRide = rideLogic.cancellationResponsibilityEliminate(id);

            // 通知服务端
            taxiService.unboundNumber(id);
            operationRecordHelper.addBusinessLog(String.format("将未支付的有责取消改为无责（直接删除罚金订单）,行程id [%d]", id));

            return RestResult.success(updateRideCancellation && updateRide);
        }
    }

    @Override
    @DSTransactional
    public RestResult<Boolean> updateOrderAmount(Long id, UpdateOrderAmountWrapper wrapper) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断ride是否处于完成待付款状态
        if (!RideStateState.ended.equals(ride.getState())) {
            return RestResult.failed("此行程未处于待付款状态");
        }

        // 判断行程是否有未付款的订单
        if (!rideOrderLogic.hasUnpaidOrder(id)) {
            return RestResult.failed("此行程没有未付款行程订单");
        }

        // 修改行程订单ride_order金额
        BigDecimal infoAmount = rideOrderLogic.recountInfoAmount(ride, wrapper.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
        boolean updateOrderAmount = new LambdaUpdateChainWrapper<>(rideOrderMapper).eq(RideOrder::getRideId, id).ne(RideOrder::getState, RideOrderState.done)
                .set(RideOrder::getAmount, wrapper.getAmount())
                .set(RideOrder::getInfoServiceAmount, infoAmount)
                .set(RideOrder::getActualAmount, wrapper.getAmount())
                .set(RideOrder::getUpdatedAt, new Date())
                .update();
        operationRecordHelper.addBusinessLog(String.format("修改未付款订单金额，行程id [%d]，金额 [%f]，信息服务费变更为 [%f]", id, wrapper.getAmount(), infoAmount));
        return RestResult.success(updateOrderAmount);
    }

    @Override
    public RestResult<RideTrackPresenter> getTrack(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }
        RideTrackPresenter res = new RideTrackPresenter();
        res.setId(id);

        if (ride.getCategory() == RideCategory.realtime) {
            RealtimeCall realtimeCall = realtimeCallMapper.selectById(ride.getRefId());
            if (ObjectUtil.isNotNull(realtimeCall)) {
                res.setCallOrigin(realtimeCall.getOrigin());
                res.setCallDestination(realtimeCall.getDestination());
            } else {
                res.setCallOrigin(ride.getCallOrigin());
                res.setCallDestination(ride.getCallDestination());
            }
        } else if (ride.getCategory() == RideCategory.appointment) {
            AppointmentCall appointmentCall = appointmentCallMapper.selectOne(Wrappers.<AppointmentCall>lambdaQuery().eq(AppointmentCall::getId, ride.getRefId()));
            if (ObjectUtil.isNotNull(appointmentCall)) {
                res.setCallOrigin(appointmentCall.getOrigin());
                res.setCallDestination(appointmentCall.getDestination());
            } else {
                res.setCallOrigin(ride.getCallOrigin());
                res.setCallDestination(ride.getCallDestination());
            }

        } else {
            return RestResult.failed("订单类型未知");
        }
        RideRouteMongo rideRouteMongo = rideRouteRepository.getByRideIdAndRideCategory(ride.getId(), "call");
        List<GeoPoint> points = new ArrayList<>();
        if (ObjectUtil.isNotNull(rideRouteMongo)) {
            for (String point : rideRouteMongo.getPoints()) {
                String[] split = StrUtil.split(point, ",");
                GeoPoint geoPoint = new GeoPoint(Convert.toDouble(split[0]), Convert.toDouble(split[1]));
                points.add(geoPoint);
            }
            //预估信息
            res.setEstimatedLocateLog(points);
            res.setEstimatedTime(Convert.toStr(rideRouteMongo.getDuration()));
            res.setEstimatedDistance(Convert.toStr(rideRouteMongo.getDistance()));
        }

        List<RideState> rideStateList = new LambdaQueryChainWrapper<>(rideStateMapper).eq(RideState::getRideId, id).list();

        if (ObjectUtil.isNotEmpty(rideStateList)) {
            // 预约单，实时单
            // 司机接单点
            if (ride.getCategory().equals(RideCategory.appointment)) {
                Optional<RideState> pick_up_contracted = rideStateList.stream().filter(i -> i.getState().equals(RideStateState.contracted)).findFirst();
                pick_up_contracted.ifPresent(rideState -> res.setPickUp(rideState.getLocate()));
            } else {
                Optional<RideState> pick_up_pickuping = rideStateList.stream().filter(i -> i.getState().equals(RideStateState.pickuping)).findFirst();
                pick_up_pickuping.ifPresent(rideState -> res.setPickUp(rideState.getLocate()));
            }

            // 实际乘客上车点
            Optional<RideState> origin = rideStateList.stream().filter(i -> i.getState().equals(RideStateState.started)).findFirst();
            origin.ifPresent(rideState -> res.setOrigin(rideState.getLocate()));

            // 实际乘客下车点
            Optional<RideState> destination = rideStateList.stream().filter(i -> i.getState().equals(RideStateState.ended)).findFirst();
            destination.ifPresent(rideState -> res.setDestination(rideState.getLocate()));
        }

        List<RideLocate> rideLocateList = new LambdaQueryChainWrapper<>(rideLocateMapper).select(RideLocate::getLocate).eq(RideLocate::getRideId, id).list();

        if (ObjectUtil.isNotEmpty(rideLocateList)) {
            res.setRideLocateLog(rideLocateList.stream().map(RideLocate::getLocate).collect(Collectors.toList()));
            //实际信息
            List<GeoPoint> realPoints = new ArrayList<>();
            for (RideLocate rideLocate : rideLocateList) {
                realPoints.add(rideLocate.getLocate());
            }
            double distance = RouteDistanceCalculator.calculateTotalDistance(realPoints);
            res.setRealDistance(Convert.toStr(Math.ceil(distance)));

            Map<RideStateState, RideState> toMap = rideStateList.stream()
                    .collect(Collectors.toMap(
                            RideState::getState,
                            Function.identity(),
                            (existing, replacement) -> existing  // 如果 key 重复，保留已存在的值
                    ));
            RideState rideStartState = toMap.get(RideStateState.started);
            RideState rideEndState = toMap.get(RideStateState.ended);
            String realTime = "0";
            if (ObjectUtil.isNotNull(rideStartState) && ObjectUtil.isNotNull(rideEndState)) {
                long between = DateUtil.between(rideStartState.getCreatedAt(), rideEndState.getCreatedAt(), DateUnit.MINUTE);
                realTime = Convert.toStr(between);
                res.setRealTime(realTime);
            }
        }


        return RestResult.success(res);
    }

    @Override
    public RestResult<Boolean> closeDriverAutomatic(Long id, CloseDriverAutomaticWrapper wrapper) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        if (Objects.isNull(ride.getDriverId())) {
            return RestResult.failed("操作失败，此行程缺少司机信息");
        }

        Driver driver = new LambdaQueryChainWrapper<>(driverMapper).select(Driver::getId).eq(Driver::getId, ride.getDriverId()).one();

        if (ObjectUtil.isEmpty(driver)) {
            return RestResult.failed("操作失败，司机信息异常");
        }

        Long logId = driverLogic.closeDriverAutomatic(ride, wrapper.getAutomaticOpenTime());

        if (Objects.isNull(logId)) {
            return RestResult.failed("操作失败");
        }

        // 清除缓存
        primaryCachePutter.deleteDriverCacheById(driver.getId());

        // 调用接口发通知
        taxiService.closeDriverAutomaticOpenNotice(driver.getId());

        // 操作日志记录
        operationRecordHelper.addBusinessLog(String.format("因行程ID [%d],关闭司机[%d]自动抢单,关闭记录为[%d]", id, driver.getId(), logId));

        return RestResult.success(true);
    }

    @Override
    // 强制取消+管理员直接取消行程
    public RestResult<Boolean> cancel(Long id) {
        log.info("行程取消ID：{}", id);
        // 校验
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        RideCancellation rideCancellation = rideCancellationMapper.selectOne(Wrappers.<RideCancellation>lambdaQuery().eq(RideCancellation::getRideId, id));

        // 判断订单能制取消
        if (!inLegallyCancelState(ride.getState()) || ObjectUtil.isNotNull(rideCancellation)) {
            return RestResult.failed("此行程无法取消");
        }

        // rideOrder
        RideOrder rideOrder = rideOrderLogic.getOneRideOrderByRideId(id);

        if (Objects.nonNull(rideOrder) && RideOrderState.done.equals(rideOrder.getState())) {
            return RestResult.failed("此行程 无法取消");
        }

        // 执行操作
        if (rideLogic.cancel(ride)) {
            //判断是否有预付费
            CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectByRideId(id);
            if (ObjectUtil.isNotNull(callPrepayOrder)) {
                //退预付款
                String refundId = IdUtil.getSnowflake(1, 1).nextIdStr();
                String txnAmtStr = Convert.toStr(callPrepayOrder.getAmount().multiply(new BigDecimal(100)).intValue());
                Map<String, String> refundMap = CmbPayClient.refund(refundId, callPrepayOrder.getNumber(), "订单取消退款", callPrepayOrder.getNumber(), refundId, txnAmtStr, txnAmtStr);
                String respPreCode = MapUtil.getStr(refundMap, "respCode");
                if (!"SUCCESS".equals(respPreCode)) {
                    log.info("订单callPrepayOrder：{},招商退预付款补充的钱返回--失败,失败原因：{}", callPrepayOrder, refundMap);
                    return RestResult.failed("退预付费失败");
                }
                log.info("订单callPrepayOrder：{},招商退预付款返回--成功", callPrepayOrder);
                //保存预付款的退款记录
                callPrepayOrderRefundLogMapper.insert(new CallPrepayOrderRefundLog().setOrderId(callPrepayOrder.getId()).setIsSuccess(true).setRefundAmount(callPrepayOrder.getAmount()).setRefundNumber(callPrepayOrder.getNumber()));
                //修改预付款退款状态
                callPrepayOrderMapper.updateById(new CallPrepayOrder().setId(callPrepayOrder.getId()).setIsRefund(true).setRefundAmount(callPrepayOrder.getAmount()));
            }

            // 通知服务端
            taxiService.unboundNumber(id);
            // ride取消后给各端的消息通知
            taxiService.updateRideStateNotice(id, "cancelled");
            // 清除司机缓存
            if (Objects.nonNull(ride.getTaxiId())) {
                taxiService.clearDriverCache(ride.getTaxiId());
            }
            //
            primaryCachePutter.deleteDispatch(ride.getTaxiId());

            taxiOnRideMapper.delete(Wrappers.<TaxiOnRide>lambdaQuery().eq(TaxiOnRide::getRideId, ride.getId()));

            // 操作日志记录
            operationRecordHelper.addBusinessLog(String.format("取消订单[%d]", id));

            //解绑隐私通话
            List<CallRelevance> callRelevances = callRelevanceMapper.selectList(Wrappers.<CallRelevance>lambdaQuery().eq(CallRelevance::getRideId, ride.getId()));
            for (CallRelevance callRelevance : callRelevances) {
                boolean unbindResult = PrivateNumberClient.unbindMobileNumber(callRelevance.getSubscriptionId());
                if (unbindResult) {
                    callRelevance.setIsEffective(false);
                    callRelevanceMapper.updateById(callRelevance);
                }
            }
            return RestResult.success(true);
        }

        return RestResult.failed("操作失败");
    }

    // ride是否处于合法的（待取消）状态中
    private boolean inLegallyCancelState(RideStateState state) {
        switch (state) {
            case contracted:
            case pickuping:
            case started:
            case ended:
            case inarea:
                return true;
            default:
                return false;
        }
    }

    @Override
    @DSTransactional
    public RestResult<Boolean> orderRefund(Long id) {
        log.info("开始执行退款操作,行程ID:{}", id);
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断该行程是否存在已付款的订单
        RideOrder rideOrder = rideLogic.getPaidOrderByRideId(id);
        if (!Objects.nonNull(rideOrder)) {
            return RestResult.failed("此行程没有已付款订单");
        }

        // 订单已退款
        if (rideOrderLogic.hasBeenRefunded(rideOrder)) {
            return RestResult.failed("此行程订单在本操作前已被退款");
        }

        log.info(String.format("开始行程退款，行程ID [%d]", id));

        // 检查行程订单是否已拥有初始化过的退款记录，如果发现拥有已完成的退款记录，则抛出异常
        // 订单不含有初始化的退款记录
        if (!rideOrderLogic.checkInitializedRefund(rideOrder.getId())) {
            rideOrderLogic.initRefund(rideOrder, "RideOrder");
        }

        boolean thirdPayRefundSuccess = false;

        // 订单不含实付金额
        if (!rideOrderLogic.hasFarePaid(rideOrder) && rideOrder.getPrepayAmount().compareTo(BigDecimal.ZERO) < 1) {
            log.info("订单不含实付金额");
            //将第三方支付退款的flag改为true，继续做后续的退款工作
            thirdPayRefundSuccess = true;
        } else {
            // 订单含有实付金额
            log.info("订单含有实付金额");
            RideTransactionLog rideTransactionLog = rideTransactionLogLogic.getLogByRideOrderId(rideOrder.getId());
            switch (rideTransactionLog.getPayThrough()) {
                case alipay:
                    thirdPayRefundSuccess = rideOrderLogic.initiateAlipayRefund(rideOrder);
                    break;
                case wxapp:
                    // 是否微信小程序支付
                    if (refundLogic.verifyWeCharPayTradeNo(rideOrder.getOutTradeNumber())) {
                        thirdPayRefundSuccess = rideOrderLogic.initiateWeChatRefund(rideOrder, Enum.RideRefundWxAppType.wxmina);
                    } else {
                        // 发起招商微信小程序退款
                        thirdPayRefundSuccess = rideOrderLogic.initiateJrcbWeChatRefund(rideOrder, Enum.RideRefundWxAppType.wxmina);
                    }
                    break;
                case jybwxapp:
                    // 表示是微信APP支付
                    if (refundLogic.verifyWeCharPayTradeNo(rideOrder.getOutTradeNumber())) {
                        thirdPayRefundSuccess = rideOrderLogic.initiateWeChatRefund(rideOrder, Enum.RideRefundWxAppType.wxapp);
                    } else {
                        // 发起农商行微信APP退款
                        thirdPayRefundSuccess = rideOrderLogic.initiateJrcbWeChatRefund(rideOrder, Enum.RideRefundWxAppType.wxapp);
                    }
                    break;
                default:
                    return RestResult.failed("暂不支持该付款方式的退款");
            }
        }

        // //第三方支付退款成功，继续做余额退款和状态修改
        if (thirdPayRefundSuccess) {
            // 订单含有余额支付金额
            if (rideOrderLogic.hasSavingPaid(rideOrder)) {
                log.info("[service]:订单含有余额支付金额");
                rechargeLogic.updateRefundedByOrderId(rideOrder.getId());
                RideTransactionLog rideTransactionLog = rideTransactionLogLogic.getLogByRideOrderId(rideOrder.getId());

                BigDecimal paySavingPaidAmount = BigDecimal.ZERO;
                BigDecimal donationSavingPaidAmount = BigDecimal.ZERO;

                if (Objects.nonNull(rideTransactionLog)) {
                    Recharge recharge = rechargeMapper.selectById(rideTransactionLog.getRechargeId());
                    paySavingPaidAmount = rideOrderLogic.getPaySavingPaidAmount(recharge);
                    donationSavingPaidAmount = rideOrderLogic.getDonationSavingPaidAmount(recharge);
                }

                Account account = accountLogic.getByCustomerId(ride.getUserId());
                if (Objects.isNull(account)) {
                    return RestResult.failed("乘客账户信息错误");
                }

                boolean updateAccount = new LambdaUpdateChainWrapper<>(accountMapper).eq(Account::getId, account.getId()).set(Account::getAmount, NumberUtil.add(account.getAmount(), paySavingPaidAmount, donationSavingPaidAmount)).set(Account::getPayAmount, NumberUtil.add(account.getPayAmount(), paySavingPaidAmount)).set(Account::getDonationAmount, NumberUtil.add(account.getDonationAmount(), donationSavingPaidAmount)).set(Account::getUpdatedAt, new Date()).update();
            } else {
                log.info("[service]:订单没有余额支付金额");
            }

            // 行程订单包含卡券抵扣的记录
            log.info("判断是否包含优惠券[开始]");
            Coupon hasCouponPaid = rideOrderLogic.getHasCouponPaid(rideOrder);
            if (Objects.nonNull(hasCouponPaid)) {
                boolean updateCoupon = new LambdaUpdateChainWrapper<>(couponMapper).eq(Coupon::getId, hasCouponPaid.getId()).set(Coupon::getHadUsed, false).set(Coupon::getUsedAt, null).set(Coupon::getUsedTimestamp, null).update();
            }
            log.info("判断是否包含优惠券[结束]");

            // 删除对应司机收入流水
            log.info("删除对应司机收入流水[开始]");
            rideOrderLogic.deleteDriverFlowLogByOrderId(rideOrder.getId(), DriverFlowLogCategory.ride_order);
            log.info("删除对应司机收入流水[结束]");

            // 删除对应公司分成流水
            log.info("删除对应公司分成流水[开始]");
            rideOrderLogic.deleteIncomeBelongingLogByOrderId(rideOrder.getId());
            log.info("删除对应公司分成流水[结束]");

            // 修改 refund
            boolean updateRefund = rideOrderLogic.updateRefundStateDoneByOrderId(rideOrder.getId());
            log.info("修改 refund 状态");

            // 修改 rideOrder
            boolean updateOrder = new LambdaUpdateChainWrapper<>(rideOrderMapper).eq(RideOrder::getId, rideOrder.getId()).set(RideOrder::getRefunded, true).update();
            log.info("修改 rideOrder 状态");

            operationRecordHelper.addBusinessLog(String.format("行程订单退款,行程id: [%d]", id));

            return RestResult.success(updateRefund && updateOrder);
        }

        return RestResult.failed("操作失败");
    }

    @Override
    @DSTransactional
    public RestResult<Boolean> customerCancellationResponsibilityRefund(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断该行程是否存在乘客的有责取消行为
        RideCancellation rideCancellation = rideLogic.getCustomerForceCancellation(id);

        if (Objects.isNull(rideCancellation) || rideCancellation.getViolate().equals(RideCancellationViolate.none) || !rideCancellation.getResponsibility().equals(RideCancellationResponsibility.customer)) {
            return RestResult.failed("此行程没有乘客有责取消行为");
        }

        // 查 cancellation_order
        CancellationOrder cancellationOrder = new LambdaQueryChainWrapper<>(cancellationOrderMapper).in(CancellationOrder::getCancelId, rideCancellation.getId()).one();

        // 判断有没有空驶费订单，没有则操作失败
        if (Objects.isNull(cancellationOrder)) {
            return RestResult.failed("数据异常，乘客有责取消缺失空驶费订单");
        }

        // 判断有责取消订单是否已完成支付，如果未完成，应该调用[有责取消退款-乘客]接口
        if (!RideOrderState.done.equals(cancellationOrder.getState())) {
            return RestResult.failed("操作失败，有责取消订单未完成支付");
        }

        // 管理员将已支付的有责取消改为无责（涉及罚金订单的退款）
        // 罚金订单已支付
        // 空驶费订单已退款
        if (cancellationOrderLogic.hasBeenRefunded(cancellationOrder)) {
            return RestResult.failed("有责取消订单在本操作前已被退款");
        }

        log.info(String.format("开始改无责退款，行程ID [%d]", id));

        // 检查行程订单是否已拥有初始化过的退款记录，如果发现拥有已完成的退款记录，则抛出异常
        // 订单不含有初始化的退款记录
        if (!cancellationOrderLogic.checkInitializedRefund(cancellationOrder.getId())) {
            cancellationOrderLogic.initRefund(cancellationOrder);
        }

        boolean thirdPayRefundSuccess = false;

        // 订单不含实付金额
        if (!cancellationOrderLogic.hasFarePaid(cancellationOrder)) {
            log.info("订单不含实付金额");
            //将第三方支付退款的flag改为true，继续做后续的退款工作
            thirdPayRefundSuccess = true;
        } else {
            //订单含有实付金额
            log.info("订单含有实付金额");
            CancellationTransactionLog log = cancellationTransactionLogLogic.getLogByCancellationOrderId(cancellationOrder.getId());
            switch (log.getPayThrough()) {
                case alipay:
                    thirdPayRefundSuccess = cancellationOrderLogic.initiateAlipayRefund(cancellationOrder);
                    break;
                case wxapp:
                    // 是否微信小程序支付
                    if (refundLogic.verifyWeCharPayTradeNo(cancellationOrder.getOutTradeNumber())) {
                        thirdPayRefundSuccess = cancellationOrderLogic.initiateWeChatRefund(cancellationOrder, Enum.RideRefundWxAppType.wxmina);
                    } else {
                        // 发起农商行微信小程序退款
                        thirdPayRefundSuccess = cancellationOrderLogic.initiateJrcbWeChatRefund(cancellationOrder, Enum.RideRefundWxAppType.wxmina);
                    }
                    break;
                case jybwxapp:
                    // 表示是微信APP支付
                    if (refundLogic.verifyWeCharPayTradeNo(cancellationOrder.getOutTradeNumber())) {
                        thirdPayRefundSuccess = cancellationOrderLogic.initiateWeChatRefund(cancellationOrder, Enum.RideRefundWxAppType.wxapp);
                    } else {
                        // 发起农商行微信APP退款
                        thirdPayRefundSuccess = cancellationOrderLogic.initiateJrcbWeChatRefund(cancellationOrder, Enum.RideRefundWxAppType.wxapp);
                    }
                    break;
                default:
                    return RestResult.failed("暂不支持该付款方式的退款");
            }
        }

        // //第三方支付退款成功，继续做余额退款和状态修改
        if (thirdPayRefundSuccess) {
            // 订单含有余额支付金额
            if (cancellationOrderLogic.hasSavingPaid(cancellationOrder)) {
                log.info("[service]:订单含有余额支付金额");
                rechargeLogic.updateRefundedByCancellationOrderId(cancellationOrder.getId());
                CancellationTransactionLog log = cancellationTransactionLogLogic.getLogByCancellationOrderId(cancellationOrder.getId());

                BigDecimal paySavingPaidAmount = BigDecimal.ONE;
                BigDecimal donationSavingPaidAmount = BigDecimal.ONE;

                if (Objects.nonNull(log)) {
                    Recharge recharge = rechargeMapper.selectById(log.getRechargeId());
                    paySavingPaidAmount = cancellationOrderLogic.getPaySavingPaidAmount(recharge);
                    donationSavingPaidAmount = cancellationOrderLogic.getDonationSavingPaidAmount(recharge);
                }

                Account account = accountLogic.getByCustomerId(ride.getUserId());
                if (Objects.isNull(account)) {
                    return RestResult.failed("乘客账户信息错误");
                }

                boolean updateAccount = new LambdaUpdateChainWrapper<>(accountMapper).eq(Account::getId, account.getId()).set(Account::getAmount, NumberUtil.add(account.getAmount(), paySavingPaidAmount, donationSavingPaidAmount)).set(Account::getPayAmount, NumberUtil.add(account.getPayAmount(), paySavingPaidAmount)).set(Account::getDonationAmount, NumberUtil.add(account.getDonationAmount(), donationSavingPaidAmount)).set(Account::getUpdatedAt, new Date()).update();
            } else {
                log.info("[service]:订单没有余额支付金额");
            }

            // 修改 refund
            log.info("修改 refund 状态");
            boolean updateRefund = cancellationOrderLogic.updateRefundStateDoneByCancellationOrderId(cancellationOrder.getId());

            // 修改 cancellation_order
            log.info("修改 cancellation_order");
            boolean updateOrder = new LambdaUpdateChainWrapper<>(cancellationOrderMapper).eq(CancellationOrder::getId, cancellationOrder.getId()).set(CancellationOrder::getRefunded, true).update();

            // 删除对应司机收入流水
            log.info("删除对应司机收入流水[开始]");
            cancellationOrderLogic.deleteDriverFlowLogByCancellationOrderId(cancellationOrder.getId());
            log.info("删除对应司机收入流水[结束]");

            // 修改 ride_cancellation
            log.info("修改 ride_cancellation[开始]");
            cancellationOrderLogic.updateForRefund(cancellationOrder.getId());
            log.info("修改 ride_cancellation[结束]");

            // 修改ride
            log.info("修改 ride 状态");
            rideLogic.updateState(id, RideStateState.cancelled);

            operationRecordHelper.addBusinessLog(String.format("将已支付的有责取消改为无责（涉及罚金订单的退款）行程id: [%d]", id));

            return RestResult.success(updateRefund && updateOrder);
        }

        return RestResult.failed("操作失败");
    }


    @Override
    public RestResult passengerInfo(String mobileNumber) {
        Integer callCount = 0;
        Integer cancelCount = 0;
        List<ArrearageRideVO> vos = new ArrayList<>();

        SimpleCallCustomer customer = customerMapper.selectOne(Wrappers.<SimpleCallCustomer>lambdaQuery().eq(SimpleCallCustomer::getMobileNumber, mobileNumber).last("limit 1").orderByDesc(SimpleCallCustomer::getId));
        //一键叫车
        PassengerRideInfo passengerRideInfo = new PassengerRideInfo();
        List<SimpleCall> simpleCalls = null;
        if (ObjectUtil.isNotNull(customer)) {
            //乘客标签
            List<CustomerTag> customerTags = customerTagMapper.selectList(Wrappers.<CustomerTag>lambdaQuery().eq(CustomerTag::getSimpleCustomerId, customer.getId()));
            if (CollUtil.isNotEmpty(customerTags)) {
                passengerRideInfo.setCustomerTag("old_people");
            }

            passengerRideInfo.setCustomerId(customer.getId());
            simpleCalls = simpleCallMapper.selectList(Wrappers.<SimpleCall>lambdaQuery().eq(SimpleCall::getCustomerId, customer.getId()).orderByDesc(SimpleCall::getCreatedAt));
            if (CollUtil.isNotEmpty(simpleCalls)) {
                Long cancelSimpleRideCount = simpleCalls.stream().filter(call -> call.getState() == SimpleCallState.cancelled).collect(Collectors.counting());
                cancelCount = cancelCount + cancelSimpleRideCount.intValue();
                callCount = callCount + simpleCalls.size();
                SimpleCall simpleCall = simpleCalls.get(0);
                passengerRideInfo.setLastCallDate(simpleCall.getCreatedAt());
                passengerRideInfo.setLastCallAddress(simpleCall.getOriginName());
                passengerRideInfo.setLastCallGeo(simpleCall.getOrigin());
                if (simpleCall.getState() != SimpleCallState.pick) {
                    passengerRideInfo.setLastCallState(simpleCall.getState().name());
                } else {
                    SimpleCallRide simpleCallRide = simpleCallRideMapper.selectOne(Wrappers.<SimpleCallRide>lambdaQuery().eq(SimpleCallRide::getRefId, simpleCall.getId()));
                    if (ObjectUtil.isNotNull(simpleCallRide)) {
                        if (simpleCallRide.getIsCancel()) {
                            SimpleCallRideCancellation ride_cancellation = new LambdaQueryChainWrapper<>(simpleCallRideCancellationMapper).select(SimpleCallRideCancellation::getTriggerBy).eq(SimpleCallRideCancellation::getRideId, simpleCallRide.getId()).one();
                            if (ObjectUtil.isNull(ride_cancellation)) {
                                passengerRideInfo.setLastCallState("cancel_system");
                            }
                            if (ride_cancellation.getTriggerBy() == SimpleCallRideCancellationTriggerBy.driver) {
                                passengerRideInfo.setLastCallState("cancel_driver");
                            } else if (ride_cancellation.getTriggerBy() == SimpleCallRideCancellationTriggerBy.customer) {
                                passengerRideInfo.setLastCallState("cancel_customer");
                            } else if (ride_cancellation.getTriggerBy() == SimpleCallRideCancellationTriggerBy.admin) {
                                passengerRideInfo.setLastCallState("cancel_admin");
                            }
                        } else {
                            if (simpleCallRide.getIsFinished()) {
                                passengerRideInfo.setLastCallState("finished");
                            } else {
                                if (simpleCallRide.getState() == SimpleCallRideState.pickUp) {
                                    passengerRideInfo.setLastCallState("pickUp");
                                } else if (simpleCallRide.getState() == SimpleCallRideState.inArea) {
                                    passengerRideInfo.setLastCallState("inArea");
                                } else if (simpleCallRide.getState() == SimpleCallRideState.start) {
                                    passengerRideInfo.setLastCallState("start");
                                } else if (simpleCallRide.getState() == SimpleCallRideState.end) {
                                    passengerRideInfo.setLastCallState("end");
                                }
                            }
                        }

                    }
                }
            }
        }

        //实时单
        User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getMobileNumber, mobileNumber));
        if (ObjectUtil.isNotNull(user)) {
            List<Ride> rides = rideMapper.selectList(Wrappers.<Ride>lambdaQuery().eq(Ride::getUserId, user.getId()).orderByDesc(Ride::getCreatedAt));
            if (CollUtil.isNotEmpty(rides)) {
                callCount = callCount + rides.size();
                for (Ride ride : rides) {
                    if (ride.getState() == RideStateState.cancelled) {
                        cancelCount = cancelCount + 1;
                    }
                }
            }
        }


        passengerRideInfo.setCallCount(callCount);
        passengerRideInfo.setCancelCount(cancelCount);

        //是否有欠款
        if (ObjectUtil.isNull(user)) {
            passengerRideInfo.setArrearageAmount(new BigDecimal(0));
        } else {
            List<RideOrder> rideOrders = rideOrderMapper.selectArrearOrdes(user.getId());
            if (CollUtil.isNotEmpty(rideOrders)) {
                List<Long> rideIds = rideOrders.stream().map(RideOrder::getRideId).collect(Collectors.toList());
                List<Ride> rides = rideMapper.selectBatchIds(rideIds);
                Map<Long, Ride> rideMap = rides.stream().collect(Collectors.toMap(Ride::getId, Function.identity()));
                for (RideOrder rideOrder : rideOrders) {
                    ArrearageRideVO vo = new ArrearageRideVO();
                    vo.setId(rideOrder.getId());
                    vo.setAmount(rideOrder.getAmount());
                    vo.setOrderNo(rideOrder.getNumber());
                    vo.setCreatedAt(rideOrder.getCreatedAt());
                    Ride ride = rideMap.get(rideOrder.getRideId());
                    if (ObjectUtil.isNotNull(ride)) {
                        Driver driver = driverMapper.selectById(ride.getDriverId());
                        if (ObjectUtil.isNotNull(driver)) {
                            vo.setDriver(new ArrearageRideVO.Driver().setId(driver.getId()).setMobileNumber(driver.getMobileNumber()).setName(driver.getName()));
                        }
                        vo.setCategory(ride.getCategory());
                        vo.setStartAddress(ride.getOriginName());
                        vo.setEndAddress(ride.getDestinationName());
                    }
                    vo.setUser(new ArrearageRideVO.User().setId(user.getId()).setMobileNumber(user.getMobileNumber()).setName(user.getName()));

                    vos.add(vo);
                }
            }
            passengerRideInfo.setArrearageRides(vos);
            Optional<BigDecimal> arrearageAmount = rideOrders.stream().map(RideOrder::getAmount).reduce(BigDecimal::add);
            if (arrearageAmount.isPresent()) {
                passengerRideInfo.setArrearageAmount(arrearageAmount.get());
            } else {
                passengerRideInfo.setArrearageAmount(new BigDecimal(0));
            }
        }


        return RestResult.success(passengerRideInfo);
    }

    @Override
    public RestResult<IPage<RideListPresenter>> suspiciousPage(AdminUser adminUser, RideQueryWrapper wrapper) {
        IPage<RideListPresenterDTO> page = rideOrderMapper.getSuspiciousPage(new Page<>(wrapper.getCurrent(), wrapper.getSize()), wrapper);

        List<RideListPresenter> listPresenters = new ArrayList<>();
        for (RideListPresenterDTO dto : page.getRecords()) {
            RideListPresenter rideListPresenter = new RideListPresenter();
            rideListPresenter.setUser(new RideListPresenter.User().setId(dto.getUserId()).setMobileNumber(dto.getUserMobileNumber()).setName(dto.getUserName()));
            rideListPresenter.setDriver(new RideListPresenter.Driver().setId(dto.getDriverId()).setMobileNumber(dto.getDriverMobileNumber()).setName(dto.getDriverName()));
            rideListPresenter.setTaxi(new RideListPresenter.Taxi().setPlateNumber(dto.getPlateNumber()));
            rideListPresenter.setId(dto.getId());
            rideListPresenter.setState(dto.getRideState());
            rideListPresenter.setPlatform(dto.getPlatform());
            rideListPresenter.setCategory(dto.getCategory());
            rideListPresenter.setCreatedAt(dto.getCreatedAt());
            rideListPresenter.setOriginName(dto.getOriginName());
            rideListPresenter.setCallOriginName(dto.getCallOriginName());
            rideListPresenter.setDestinationName(dto.getDestinationName());
            rideListPresenter.setCallDestinationName(dto.getCallDestinationName());
            rideListPresenter.setArea(new RideListPresenter.Area().setName(dto.getAreaName()));
            rideListPresenter.setRideOrder(new RideListPresenter.RideOrder().setId(dto.getRideOrderId()).setAmount(dto.getRideOrderAmount()).setPaidThrough(dto.getRideOrderPaidThrough()).setPresetThrough(dto.getRideOrderPresetThrough()).setRefunded(dto.getRideOrderRefunded()).setState(dto.getRideOrderState()));


            listPresenters.add(rideListPresenter);
        }


        IPage<RideListPresenter> suspiciousPage = new Page<>();
        suspiciousPage.setCurrent(page.getCurrent());
        suspiciousPage.setPages(page.getPages());
        suspiciousPage.setSize(page.getSize());
        suspiciousPage.setTotal(page.getTotal());
        suspiciousPage.setRecords(listPresenters);
        return RestResult.success(suspiciousPage);
    }

    @Override
    public List<Ride> getListByCallIds(List<Long> callIds) {
        return rideMapper.selectList(Wrappers.<Ride>lambdaQuery().in(Ride::getRefId, callIds));
    }

    @Override
    public RestResult privacyCallLogByRideId(Long rideId) {
        Dict result = new Dict();
        List<CallRelevance> relevances = callRelevanceMapper.selectList(Wrappers.<CallRelevance>lambdaQuery().eq(CallRelevance::getRideId, rideId).orderByDesc(CallRelevance::getCreatedAt));

        for (CallRelevance relevance : relevances) {
            Driver driver = driverMapper.selectById(relevance.getDriverId());
            if (ObjectUtil.isNotNull(driver)) {
                if (relevance.getCallerNumber().equals(driver.getMobileNumber())) {
                    relevance.setCallerNumber(driver.getMobileNumber() + "(司机)");
                } else if (relevance.getCalleeNumber().equals(driver.getMobileNumber())) {
                    relevance.setCalleeNumber(driver.getMobileNumber() + "(司机)");
                }
            }
            User user = userMapper.selectById(relevance.getCustomerId());
            if (ObjectUtil.isNotNull(user)) {
                if (relevance.getCallerNumber().equals(user.getMobileNumber())) {
                    relevance.setCallerNumber(user.getMobileNumber() + "(乘客)");
                } else if (relevance.getCalleeNumber().equals(user.getMobileNumber())) {
                    relevance.setCalleeNumber(user.getMobileNumber() + "(乘客)");
                }
            }
        }
        return RestResult.success(relevances);
    }

    @Override
    public RestResult willRefundDetail(Long id) {
        Ride ride = rideMapper.selectById(id);
        if (ObjectUtil.isNull(ride)) {
            return RestResult.failed("行程不存在");
        }
        RideOrder rideOrder = rideOrderMapper.selectOne(Wrappers.<RideOrder>lambdaQuery().eq(RideOrder::getRideId, ride.getId()));
        if (ObjectUtil.isNull(rideOrder)) {
            return RestResult.failed("还未生成订单");
        }

        Boolean isPrepay = false;
        Integer category = null;
        //已退金额
        BigDecimal refundedAmount = new BigDecimal("0");
        BigDecimal prepayAmount = BigDecimal.ZERO;
        if (ride.getCategory() == RideCategory.appointment) {
            AppointmentCall appointmentCall = appointmentCallMapper.selectById(ride.getRefId());
            isPrepay = ObjectUtil.isNull(appointmentCall.getNeedPrepay()) ? false : appointmentCall.getNeedPrepay();
            if (isPrepay) {
                CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectOne(Wrappers.<CallPrepayOrder>lambdaQuery()
                        .eq(CallPrepayOrder::getCallId, appointmentCall.getId())
                        .eq(CallPrepayOrder::getCallCategory, 1));
                prepayAmount = callPrepayOrder.getAmount();
            }

        } else if (ride.getCategory() == RideCategory.realtime) {
            RealtimeCall realtimeCall = realtimeCallMapper.selectById(ride.getRefId());
            isPrepay = realtimeCall.getNeedPrepay();
            if (realtimeCall.getNeedPrepay()) {
                CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectOne(Wrappers.<CallPrepayOrder>lambdaQuery()
                        .eq(CallPrepayOrder::getCallId, realtimeCall.getId())
                        .eq(CallPrepayOrder::getCallCategory, 0));
                prepayAmount = callPrepayOrder.getAmount();
            }
        } else {
            return RestResult.failed("暂不支持该类型订单的退款");
        }
        List<RideRefundLog> rideRefundLogs = rideRefundLogMapper.selectList(
                Wrappers.<RideRefundLog>lambdaQuery()
                        .eq(RideRefundLog::getRideId, ride.getId())
                        .eq(RideRefundLog::getState, 2));
        if (CollUtil.isNotEmpty(rideRefundLogs)) {
            BigDecimal reduce = rideRefundLogs.stream().map(RideRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            refundedAmount = reduce;
        }

        BigDecimal expectedRefund = rideOrder.getTotalPaid().subtract(refundedAmount);


        RideWillRefundPresenter presenter = new RideWillRefundPresenter();
        presenter.setRideId(ride.getId());
        presenter.setOrderId(rideOrder.getId());
        presenter.setOrderAmount(rideOrder.getAmount());
        presenter.setHasOnline(ride.getHasOnline());
        presenter.setIsPrepayOrder(isPrepay);
        presenter.setPrepayAmount(prepayAmount);
        presenter.setCategory(ride.getCategory().getCode());
        presenter.setRefundedAmount(refundedAmount);
        presenter.setExpectedRefund(expectedRefund);
        presenter.setFarePaid(rideOrder.getFarePaid());
        //其他费用明细
        RideOrderDetail rideOrderDetail = rideOrderDetailMapper.selectOne(Wrappers.<RideOrderDetail>lambdaQuery().eq(RideOrderDetail::getOrderId, rideOrder.getId()));
        if (ObjectUtil.isNotNull(rideOrderDetail)) {
            presenter.setTollFee(rideOrderDetail.getTollFee());
            presenter.setOtherFee(rideOrderDetail.getOtherFee());
        }
        //优惠券
        if (ObjectUtil.isNotNull(rideOrder.getCouponId())) {
            Coupon coupon = couponMapper.selectById(rideOrder.getCouponId());
            if (ObjectUtil.isNotNull(coupon)) {
                BigDecimal couponAmount = ObjectUtil.isNull(coupon.getActualDiscount()) ? BigDecimal.ZERO : coupon.getActualDiscount();
                presenter.setCouponAmount(couponAmount);
                presenter.setCouponType(coupon.getSaleCategory() == 0 ? "free" : "red");
            }
        }
        return RestResult.success(presenter);
    }

    @Override
    public RestResult privacyCallDetailLog(String subscriptionId) {
        List<CallEndSend> callEndSends = callEndSendMapper.selectList(Wrappers.<CallEndSend>lambdaQuery().in(CallEndSend::getSubid, subscriptionId));
        return RestResult.success(callEndSends);
    }

    @Override
    public RestResult finishOrder(Long rideId) {
        //call
        Ride ride = rideMapper.selectById(rideId);
        if (ObjectUtil.isNull(ride)) {
            return RestResult.failed("操作失败,行程不存在");
        }
        RideOrder rideOrder = rideOrderMapper.selectOne(Wrappers.<RideOrder>lambdaQuery().eq(RideOrder::getRideId, rideId));
        if (ObjectUtil.isNull(rideOrder)) {
            return RestResult.failed("操作失败,订单还未生成");
        }
        if (ride.getState() != RideStateState.ended) {
            return RestResult.failed("操作失败,订单状态不正确");
        }
        CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectByRideId(rideId);
        if (callPrepayOrder.getAmount().compareTo(rideOrder.getAmount()) >= 0) {
            String body = HttpRequest.post("https://taxi-online.njydi.cn/payment/ride/complete_order").body(JSON.toJSONString(Dict.create().set("prepayAmount", callPrepayOrder.getAmount()).set("amount", rideOrder.getAmount()).set("orderId", rideOrder.getId()).set("rideId", rideId))).execute().body();
            System.out.println(body);
            JSONObject json = JSON.parseObject(body);
            Integer code = json.getInteger("code");
            if (ObjectUtil.isNull(code) || code != 0) {
                return RestResult.failed(json.getString("msg"));
            }
        }
        return RestResult.success();
    }

    @Override
    public RestResult getRefundCount(Long callId, Integer callCategory) {
        CallPrepayOrder callPrepayOrder = callPrepayOrderMapper.selectOne(Wrappers.<CallPrepayOrder>lambdaQuery().eq(CallPrepayOrder::getCallId, callId).eq(CallPrepayOrder::getCallCategory, callCategory));
        if (ObjectUtil.isNull(callPrepayOrder)) {
            return RestResult.failed("预付信息不存在");
        }
        List<CallPrepayOrderRefundLog> callPrepayOrderRefundLogs = callPrepayOrderRefundLogMapper.selectList(Wrappers.<CallPrepayOrderRefundLog>lambdaQuery().eq(CallPrepayOrderRefundLog::getOrderId, callPrepayOrder.getId()).eq(CallPrepayOrderRefundLog::getIsSuccess, true));
        BigDecimal refundTotal = new BigDecimal(0.0);
        if (CollUtil.isNotEmpty(callPrepayOrderRefundLogs)) {
            refundTotal = callPrepayOrderRefundLogs.stream().map(CallPrepayOrderRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        return RestResult.success(Dict.create().set("refundTotal", refundTotal));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult createOrderBill(Integer rideId, BigDecimal taxiAmount, BigDecimal tollAmount, BigDecimal otherAmount) {
        Ride ride = rideMapper.selectById(rideId);
        if (ObjectUtil.isNull(ride)) {
            return RestResult.failed("行程不存在");
        }
        if (ride.getState() != RideStateState.ended) {
            return RestResult.failed("行程状态不正确！");
        }
        RideOrder rideOrder = rideOrderMapper.selectOne(Wrappers.<RideOrder>lambdaQuery().eq(RideOrder::getRideId, rideId));
        if (ObjectUtil.isNotNull(rideOrder)) {
            return RestResult.failed("行程已生成账单,无需重复操作!");
        }
        //先生成RideOrder
        RideOrder order = new RideOrder();
        RideOrderDetail detail = new RideOrderDetail();

        //TODO 线上车费计算
        if (ObjectUtil.isNotNull(ride.getHasOnline()) && ride.getHasOnline()) {
            CallRouteMongo callRouteMongo = callRouteMongoRepository.findByCallIdAndIsRealtime(ride.getRefId(), ride.getCategory() == RideCategory.realtime);
            if (ObjectUtil.isNull(callRouteMongo)) {
                return RestResult.failed("线上车费计算失败！请确认此单是否正确");
            }
            JSONObject callRouteJsonObject = JSON.parseObject(callRouteMongo.getCallRoute());
            JSONObject onlinePriceObj = callRouteJsonObject.getJSONObject("onlinePrice");

            order.setRideId(Long.valueOf(rideId));
            order.setAmount(onlinePriceObj.getBigDecimal("totalFee"));
            order.setUserId(ride.getUserId());
            order.setInfoServiceAmount(onlinePriceObj.getBigDecimal("infoServiceFee"));
            order.setPresetThrough(RideOrderPaidThrough.online);
            Identifier idg = new Identifier("R");
            order.setNumber(idg.generate());
            order.setState(RideOrderState.init);
            rideOrderMapper.insert(order);

            detail.setRideId(Long.valueOf(rideId));
            detail.setOrderId(order.getId());
            detail.setTollFee(tollAmount);
            detail.setTaxiFee(onlinePriceObj.getBigDecimal("totalFee"));
            detail.setOtherFee(otherAmount);
            detail.setExceedDuration(onlinePriceObj.getLong("exceedDuration"));
            detail.setStartingDuration(onlinePriceObj.getLong("startingDuration"));
            detail.setExceedMileage(onlinePriceObj.getBigDecimal("exceedMileage"));
            detail.setStartingMileage(onlinePriceObj.getBigDecimal("startingMileage"));
            detail.setEmptyBackFee(onlinePriceObj.getBigDecimal("emptyBackFee"));
            detail.setInfoServiceFee(onlinePriceObj.getBigDecimal("infoServiceFee"));
            //平台营收=乘客信息服务费+司机抽成金额
            Dict driverCommissionDict = calculateDriverCommission(ride, callRouteJsonObject, tollAmount, otherAmount);
            detail.setDriverCommission(driverCommissionDict.getBigDecimal("driverCommissionAmount"));
            detail.setDriverEarningOtherFee(driverCommissionDict.getBigDecimal("otherFee"));
            detail.setDriverEarningTollFee(driverCommissionDict.getBigDecimal("tollFee"));
            detail.setDriverEarningPriceMarkup(driverCommissionDict.getBigDecimal("priceMarkup"));
            detail.setPlatformEarning(BigDecimal.ZERO);
            detail.setHolidayFee(getBigDecimalOrDefault(onlinePriceObj, "holidayFee", BigDecimal.ZERO));
            detail.setBadWeatherFee(getBigDecimalOrDefault(onlinePriceObj, "badWeatherFee", BigDecimal.ZERO));
            detail.setPriceMarkup(Convert.toBigDecimal(ride.getPriceMarkup()));
            detail.setWaitingFee(new BigDecimal(0.00));
            detail.setExceedTimeFee(getBigDecimalOrDefault(onlinePriceObj, "exceedTimeFee", BigDecimal.ZERO));
            detail.setExceedMileageFee(getBigDecimalOrDefault(onlinePriceObj, "exceedMileageFee", BigDecimal.ZERO));
            detail.setStartingFee(getBigDecimalOrDefault(onlinePriceObj, "startingFee", BigDecimal.ZERO));
            rideOrderDetailMapper.insert(detail);

        } else {
            //线下车费计算
            BigDecimal totalAmount = taxiAmount.add(tollAmount).add(otherAmount);
            order.setRideId(Long.valueOf(rideId));
            order.setAmount(taxiAmount);
            order.setUserId(ride.getUserId());
            BigDecimal infoAmount = rideOrderLogic.recountInfoAmount(ride, totalAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
            order.setInfoServiceAmount(infoAmount);
            order.setFarePaid(totalAmount);
            order.setPresetThrough(RideOrderPaidThrough.online);
            Identifier idg = new Identifier("R");
            order.setNumber(idg.generate());
            order.setState(RideOrderState.init);

            rideOrderMapper.insert(order);

            detail.setRideId(Long.valueOf(rideId));
            detail.setOrderId(order.getId());
            detail.setTollFee(tollAmount);
            detail.setTaxiFee(taxiAmount);
            detail.setOtherFee(otherAmount);
            rideOrderDetailMapper.insert(detail);
        }
        operationRecordHelper.addBusinessLog(String.format("管理员生成订单账单，行程id [%d]", ride.getId()));
        return RestResult.success();
    }

    @Override
    public OrderManageAllVo getAll(AdminUser adminUser, OrderManageQueryDto query) {
        ExecutorService customPool = Executors.newFixedThreadPool(10);
        OrderManageAllVo allVo = new OrderManageAllVo();
        List<OrderManageVo> list = new ArrayList<>();
        //线上订单
        CompletableFuture<List<OrderManageVo>> onlineOrderFuture = CompletableFuture.supplyAsync(() -> {
            try {
                List<OrderManageVo> orderManageVos = new ArrayList<>();
                LambdaQueryWrapper<Ride> rideLambdaQueryChainWrapper = new LambdaQueryWrapper<Ride>().
                        in(ObjectUtil.isNotEmpty(query.getIds()), Ride::getId, query.getIds()).
                        eq(ObjectUtil.isNotEmpty(query.getCategory()), Ride::getCategory, query.getCategory()).
                        eq(ObjectUtil.isNotEmpty(query.getDriverId()), Ride::getDriverId, query.getDriverId()).
                        eq(ObjectUtil.isNotEmpty(query.getCustomerId()), Ride::getUserId, query.getCustomerId()).
                        ge(ObjectUtil.isNotEmpty(query.getStartDate()), Ride::getCreatedAt, query.getStartDate()).
                        le(ObjectUtil.isNotEmpty(query.getEndDate()), Ride::getCreatedAt, query.getEndDate() + " 23:59:59");
                //订单状态
                if (StringUtils.isNotBlank(query.getOrderState())) {
                    if (query.getOrderState().equals("waiting") || query.getOrderState().equals("contracted") ||
                            query.getOrderState().equals("pickuping") || query.getOrderState().equals("inarea") ||
                            query.getOrderState().equals("started") || query.getOrderState().equals("ended") ||
                            query.getOrderState().equals("completed") || query.getOrderState().equals("marked") ||
                            query.getOrderState().equals("cancelled") || query.getOrderState().equals("forcecancelled")) {

                        rideLambdaQueryChainWrapper.eq(Ride::getState, RideStateState.valueOf(query.getOrderState()));
                    } else {
                        //无
                        rideLambdaQueryChainWrapper.eq(Ride::getState, -1);
                    }
                }
                if (StrUtil.isNotBlank(query.getPlateNumber())) {
                    List<Taxi> taxis = taxiMapper.selectLikeTaxisByPlateNumber(query.getPlateNumber());
                    List<Long> taxisCollect = taxis.stream().map(Taxi::getId).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(taxisCollect)) {
                        rideLambdaQueryChainWrapper.in(Ride::getTaxiId, taxisCollect);
                    } else {
                        return orderManageVos;
                    }
                }
                FilterHandler filterHandler = new FilterHandler(adminUser, query.getCantonId(), query.getCompanyId());
                switch (adminUser.getAccountType()) {
                    case platform:
                        rideLambdaQueryChainWrapper.eq(Objects.nonNull(query.getCantonId()), Ride::getCantonId, query.getCantonId());
                        rideLambdaQueryChainWrapper.eq(Objects.nonNull(query.getCompanyId()), Ride::getCompanyId, query.getCompanyId());
                        break;
                    case canton:
                        if (Objects.nonNull(query.getCantonId()) && filterHandler.getCantonIds().contains(query.getCantonId())) {
                            rideLambdaQueryChainWrapper.eq(Ride::getCantonId, query.getCantonId());
                        } else {
                            rideLambdaQueryChainWrapper.in(Ride::getCantonId, filterHandler.getCantonIds());
                        }
                        if (Objects.nonNull(query.getCompanyId()) && filterHandler.getCompanyIds().contains(query.getCompanyId())) {
                            rideLambdaQueryChainWrapper.eq(Ride::getCompanyId, query.getCompanyId());
                        }
                        break;
                    case company:
                        if (Objects.nonNull(query.getCompanyId()) && filterHandler.getCompanyIds().contains(query.getCompanyId())) {
                            rideLambdaQueryChainWrapper.eq(Ride::getCompanyId, query.getCompanyId());
                        } else {
                            rideLambdaQueryChainWrapper.in(Ride::getCompanyId, filterHandler.getCompanyIds());
                        }
                        break;
                }
                // 1. 乘客搜索
                String customerSearch = query.getCustomerSearch();
                if (ObjectUtil.isNotEmpty(customerSearch)) {
                    List<User> userList = new LambdaQueryChainWrapper<>(userMapper).select(User::getId).eq(this.isPhoneNum(customerSearch), User::getMobileNumber, customerSearch).like(!this.isPhoneNum(customerSearch), User::getName, customerSearch).last("limit 20").list();

                    if (ObjectUtil.isEmpty(userList)) {
                        return orderManageVos;
                    } else {
                        List<Long> userIds = userList.stream().map(User::getId).collect(Collectors.toList());
                        rideLambdaQueryChainWrapper.in(Ride::getUserId, userIds);
                    }
                }
                // 2. 司机搜索
                String driverSearch = query.getDriverSearch();
                if (ObjectUtil.isNotEmpty(driverSearch)) {
                    List<Driver> driverList = new LambdaQueryChainWrapper<>(driverMapper).select(Driver::getId).eq(this.isPhoneNum(driverSearch), Driver::getMobileNumber, driverSearch).like(!this.isPhoneNum(driverSearch), Driver::getName, driverSearch).list();

                    if (ObjectUtil.isEmpty(driverList)) {
                        return orderManageVos;
                    } else {
                        List<Long> driverIds = driverList.stream().map(Driver::getId).collect(Collectors.toList());
                        rideLambdaQueryChainWrapper.in(Ride::getDriverId, driverIds);
                    }
                }

                rideLambdaQueryChainWrapper.in(Ride::getIsImitate, filterHandler.getIsImitates()).orderByDesc(Ride::getId);
                List<Ride> rides = rideMapper.selectList(rideLambdaQueryChainWrapper);
                if (CollectionUtils.isEmpty(rides)) {
                    return orderManageVos;
                }
                for (Ride ride : rides) {
                    OrderManageVo vo = new OrderManageVo();
                    vo.setId(ride.getId());
                    vo.setTabName("线上订单");
                    //平台
                    vo.setPlatform(ride.getPlatform().getDesc());
                    //类型
                    vo.setCategory(ride.getCategory().getDesc());
                    vo.setOrderId(ride.getId().toString());
                    //司机信息
                    if (ObjectUtils.isNotEmpty(ride.getDriverId())) {
                        Driver driver = driverMapper.selectById(ride.getDriverId());
                        if (ObjectUtils.isNotEmpty(driver)) {
                            vo.setDriverId(driver.getId().toString());
                            vo.setDriverName(driver.getName());
                            vo.setDriverPhoneNumber(driver.getMobileNumber());
                        }
                    }
                    //车辆信息
                    if (ObjectUtils.isNotEmpty(ride.getTaxiId())) {
                        Taxi taxi = taxiMapper.selectById(ride.getTaxiId());
                        if (ObjectUtils.isNotEmpty(taxi)) {
                            vo.setVehicleNumber(taxi.getPlateNumber());
                        }
                    }
                    //乘客信息
                    if (ObjectUtils.isNotEmpty(ride.getUserId())) {
                        User user = userMapper.selectById(ride.getUserId());
                        if (ObjectUtils.isNotEmpty(user)) {
                            vo.setPassengerId(user.getId().toString());
                            vo.setPassengerName(user.getName());
                            vo.setPassengerPhoneNumber(user.getMobileNumber());
                        }
                    }
                    //下单时间
                    vo.setOrderTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(ride.getCreatedAt()));
                    //行政区
                    GeoArea geoArea = geoAreaMapper.selectById(ride.getAreaId());
                    if (ObjectUtils.isNotEmpty(geoArea)) {
                        vo.setAreaName(geoArea.getName());
                    }
                    //预约起点、终点
                    vo.setCallOriginName(ride.getCallOriginName());
                    vo.setCallDestinationName(ride.getCallDestinationName());
                    //实际起点、终点
                    vo.setOriginName(ride.getOriginName());
                    vo.setDestinationName(ride.getDestinationName());
                    //计价方式
                    if (null != ride.getHasOnline()) {
                        if (ride.getHasOnline()) {
                            vo.setPricingMethod("线上计价");
                        } else {
                            vo.setPricingMethod("计价器计价");
                        }
                    }
                    //是否预付单
                    if (ride.getCategory() == RideCategory.realtime) {
                        RealtimeCall realtimeCall = realtimeCallMapper.selectById(ride.getRefId());
                        if (ObjectUtil.isNotNull(realtimeCall)) {
                            if (realtimeCall.getNeedPrepay()) {
                                vo.setNeedPrepay("是");
                            } else {
                                vo.setNeedPrepay("否");
                            }

                        }
                    } else if (ride.getCategory() == RideCategory.appointment) {
                        AppointmentCall appointmentCall = appointmentCallMapper.selectById(ride.getRefId());
                        if (ObjectUtil.isNotNull(appointmentCall)) {
                            if (null != appointmentCall.getNeedPrepay()) {
                                if (appointmentCall.getNeedPrepay()) {
                                    vo.setNeedPrepay("是");
                                } else {
                                    vo.setNeedPrepay("否");
                                }
                            } else {
                                vo.setNeedPrepay("否");
                            }
                        }
                    }
                    //支付信息
                    LambdaQueryWrapper<RideOrder> rideOrderWrapper = new LambdaQueryWrapper<RideOrder>().eq(RideOrder::getRideId, ride.getId());
                    RideOrder rideOrder = rideOrderMapper.selectOne(rideOrderWrapper);
                    RideCancellation rideCancellation = new LambdaQueryChainWrapper<>(rideCancellationMapper).
                            select(RideCancellation::getId, RideCancellation::getRideId, RideCancellation::getTriggerBy,
                                    RideCancellation::getResponsibility, RideCancellation::getViolate, RideCancellation::getPenalty)
                            .eq(RideCancellation::getRideId, ride.getId()).one();
                    LambdaQueryWrapper<CancellationOrder> lambdaQueryWrapper = new LambdaQueryWrapper();
                    if (ObjectUtils.isNotEmpty(rideOrder)) {
                        vo.setAmount(rideOrder.getAmount());
                        if (null != rideOrder.getPaidThrough()) {
                            vo.setPaidThrough(rideOrder.getPaidThrough().getDesc());
                        }
                        if (null != rideOrder.getState()) {
                            vo.setPaidState(rideOrder.getState().getDesc());
                            vo.setPaidStateEn(rideOrder.getState());
                        }
                        if (null != rideOrder.getPresetThrough()) {
                            vo.setPresetThrough(rideOrder.getPresetThrough());
                        }
                        if (rideOrder.getRefunded()) {
                            vo.setPaidState("全部退款");
                        } else {
                            List<RideRefundLog> refundLogs = rideRefundLogMapper.selectList(Wrappers.<RideRefundLog>lambdaQuery()
                                    .in(RideRefundLog::getState, Arrays.asList(0, 2))
                                    .eq(RideRefundLog::getRideId, ride.getId()));
                            BigDecimal refundAmount = refundLogs.stream().filter(x -> x.getState() != 1).map(RideRefundLog::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                            if (!rideOrder.getRefunded() && refundAmount.compareTo(BigDecimal.ZERO) > 0) {
                                vo.setPartialRefund(true);
                                vo.setPaidState("部分退款");
                            }
                        }
                    }
                    if (4 == ride.getState().getCode()) {
                        vo.setOrderState("到达未付款");
                        vo.setOrderStateEn("ended");
                    } else if (5 == ride.getState().getCode()) {
                        vo.setOrderState("已付款待评价");
                        vo.setOrderStateEn("completed");
                    } else if (3 == ride.getState().getCode()) {
                        vo.setOrderState("乘客已上车");
                        vo.setOrderStateEn("started");
                    } else if (2 == ride.getState().getCode()) {
                        vo.setOrderState("已接单");
                        vo.setOrderStateEn("pickuping");
                    } else if (1 == ride.getState().getCode()) {
                        vo.setOrderState("已接受预约");
                        vo.setOrderStateEn("contracted");
                    } else if (6 == ride.getState().getCode()) {
                        vo.setOrderState(ride.getState().getDesc());
                        vo.setOrderStateEn("marked");
                    } else if (7 == ride.getState().getCode()) {
                        vo.setOrderState(ride.getState().getDesc());
                        vo.setOrderStateEn("cancelled");
                        //已取消（订单状态）
                        if (ObjectUtils.isNotEmpty(rideCancellation)) {
                            int code = rideCancellation.getTriggerBy().getCode();
                            if (3 == code) {
                                vo.setOrderState("管理员取消");
                            } else if (1 == code) {
                                vo.setOrderState("乘客取消");
                            } else {
                                vo.setOrderState("司机取消");
                            }
                            //支付信息
                            lambdaQueryWrapper.eq(CancellationOrder::getCancelId, rideCancellation.getId());
                            CancellationOrder cancellationOrder = cancellationOrderMapper.selectOne(lambdaQueryWrapper);
                            if (ObjectUtils.isNotEmpty(cancellationOrder)) {
                                vo.setPaidState(cancellationOrder.getState().getDesc());
                                if (null != cancellationOrder.getPaidThrough()) {
                                    vo.setPaidThrough(cancellationOrder.getPaidThrough().getDesc());
                                }
                                if (null != cancellationOrder.getAmount()) {
                                    vo.setAmount(cancellationOrder.getAmount());
                                }
                                vo.setPaidStateEn(cancellationOrder.getState());
                            }
                        } else {
                            vo.setOrderState("已取消");
                        }

                    } else if (8 == ride.getState().getCode()) {
                        vo.setOrderState(ride.getState().getDesc());
                        vo.setOrderStateEn("forcecancelled");

                        if (ObjectUtils.isNotEmpty(rideCancellation)) {
                            //有责取消
                            lambdaQueryWrapper.eq(CancellationOrder::getCancelId, rideCancellation.getId());
                            CancellationOrder cancellationOrder = cancellationOrderMapper.selectOne(lambdaQueryWrapper);
                            int code = rideCancellation.getTriggerBy().getCode();
                            if (0 == code) {
                                vo.setOrderState(ride.getState().getDesc());
                            } else if (1 == code) {
                                //乘客
                                if (null != rideCancellation.getPenalty() && rideCancellation.getPenalty().compareTo(BigDecimal.ZERO) > 0) {
                                    vo.setOrderState("乘客有责取消");
                                } else {
                                    vo.setOrderState("乘客无责取消");
                                }
                            } else if (2 == code) {
                                if (null != rideCancellation.getPenalty() && rideCancellation.getPenalty().compareTo(BigDecimal.ZERO) > 0) {
                                    vo.setOrderState("司机有责取消");
                                } else {
                                    vo.setOrderState("司机无责取消");
                                }
                            } else if (3 == code) {
                                if (0 == rideCancellation.getResponsibility().getCode()) {
                                    vo.setOrderState("管理员取消");
                                } else if (1 == rideCancellation.getResponsibility().getCode()) {
                                    if (null != rideCancellation.getPenalty() && rideCancellation.getPenalty().compareTo(BigDecimal.ZERO) > 0) {
                                        vo.setOrderState("乘客有责/管理员取消");
                                    } else {
                                        vo.setOrderState("乘客无责/管理员取消");
                                    }
                                } else if (2 == rideCancellation.getResponsibility().getCode()) {
                                    if (null != rideCancellation.getPenalty() && rideCancellation.getPenalty().compareTo(BigDecimal.ZERO) > 0) {
                                        vo.setOrderState("司机有责/管理员取消");
                                    } else {
                                        vo.setOrderState("司机无责/管理员取消");
                                    }
                                }
                            }
                            //支付信息
                            if (ObjectUtils.isNotEmpty(cancellationOrder)) {
                                vo.setPaidState(cancellationOrder.getState().getDesc());
                                if (null != cancellationOrder.getPaidThrough()) {
                                    vo.setPaidThrough(cancellationOrder.getPaidThrough().getDesc());
                                }
                                if (null != cancellationOrder.getAmount()) {
                                    vo.setAmount(cancellationOrder.getAmount());
                                }
                                vo.setPaidStateEn(cancellationOrder.getState());
                            }
                        }
                    } else if (9 == ride.getState().getCode()) {
                        vo.setOrderState(ride.getState().getDesc());
                        vo.setOrderStateEn("inarea");
                    }
                    orderManageVos.add(vo);
                }
                return orderManageVos;
            } catch (Exception e) {
                log.error("获取线上订单列表异常:{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }, customPool).exceptionally(ex -> {
            log.error("获取线上订单列表异常:{}", ex.getMessage());
            return null;
        });


        //一键叫车行程
        CompletableFuture<List<OrderManageVo>> oneClickFuture = CompletableFuture.supplyAsync(() -> {
            try {
                List<OrderManageVo> oneClickRideHailingS = simpleCallRideService.getOneClickOrderManageVoList(adminUser, query);
                return oneClickRideHailingS;
            } catch (Exception e) {
                log.error("获取一键叫车行程订单异常:{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }, customPool).exceptionally(ex -> {
            log.error("获取一键叫车行程订单异常:{}", ex.getMessage());
            return null;
        });
        //助老屏
        CompletableFuture<List<OrderManageVo>> elderlyFuture = CompletableFuture.supplyAsync(() -> {
            try {
                List<OrderManageVo> elderlyScreens = simpleCallRideService.getOldSimpleOrderManageVoList(adminUser, query);
                return elderlyScreens;
            } catch (Exception e) {
                log.error("获取助老屏订单异常:{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }, customPool).exceptionally(ex -> {
            log.error("获取助老屏订单异常:{}", ex.getMessage());
            return null;
        });
        //扫码行程
        CompletableFuture<List<OrderManageVo>> scanCodeFuture = CompletableFuture.supplyAsync(() -> {
            try {
                List<OrderManageVo> scanCodes = scanRideOrderService.getSweepOrderAll(adminUser, query);
                return scanCodes;
            } catch (Exception e) {
                log.error("获取扫码行程订单异常:{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }, customPool).exceptionally(ex -> {
            log.error("获取扫码行程订单异常:{}", ex.getMessage());
            return null;
        });

        //异常订单
        CompletableFuture<List<OrderManageVo>> abnormalFuture = CompletableFuture.supplyAsync(() -> {
            try {
                List<OrderManageVo> orderManageVos = new ArrayList<>();
                //订单状态
                if (StringUtils.isNotBlank(query.getOrderState())) {
                    if (query.getOrderState().equals("waiting") || query.getOrderState().equals("contracted") ||
                            query.getOrderState().equals("pickuping") || query.getOrderState().equals("inarea") ||
                            query.getOrderState().equals("started") || query.getOrderState().equals("ended") ||
                            query.getOrderState().equals("completed") || query.getOrderState().equals("marked") ||
                            query.getOrderState().equals("cancelled") || query.getOrderState().equals("forcecancelled")) {

                        query.setState(RideStateState.valueOf(query.getOrderState()));
                    } else {
                        //无
                        query.setState(RideStateState.valueOf(""));
                    }
                }
                List<RideListPresenterDTO> abnormalList = rideOrderMapper.getAbnormalList(query);
                if (CollectionUtils.isNotEmpty(abnormalList)) {
                    for (RideListPresenterDTO rideListPresenterDTO : abnormalList) {
                        OrderManageVo vo = new OrderManageVo();
                        vo.setId(rideListPresenterDTO.getId());
                        vo.setTabName("异常订单");
                        if (null != rideListPresenterDTO.getPlatform()) {
                            vo.setPlatform(rideListPresenterDTO.getPlatform().getDesc());
                        }
                        if (null != rideListPresenterDTO.getCategory()) {
                            vo.setCategory(rideListPresenterDTO.getCategory().getDesc());
                        }

                        vo.setOrderId(rideListPresenterDTO.getId().toString());
                        //司机
                        vo.setDriverId(rideListPresenterDTO.getDriverId().toString());
                        vo.setDriverName(rideListPresenterDTO.getDriverName());
                        vo.setDriverPhoneNumber(rideListPresenterDTO.getDriverMobileNumber());
                        vo.setVehicleNumber(rideListPresenterDTO.getPlateNumber());
                        //乘客
                        vo.setPassengerId(rideListPresenterDTO.getUserId().toString());
                        vo.setPassengerName(rideListPresenterDTO.getUserName());
                        vo.setPassengerPhoneNumber(rideListPresenterDTO.getUserMobileNumber());
                        vo.setOrderTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(rideListPresenterDTO.getCreatedAt()));
                        if (StringUtils.isNotBlank(rideListPresenterDTO.getAreaName())) {
                            vo.setAreaName(rideListPresenterDTO.getAreaName());
                        }
                        if (StringUtils.isNotBlank(rideListPresenterDTO.getCallOriginName())) {
                            vo.setCallOriginName(rideListPresenterDTO.getCallOriginName());
                        }
                        if (StringUtils.isNotBlank(rideListPresenterDTO.getCallDestinationName())) {
                            vo.setCallDestinationName(rideListPresenterDTO.getCallDestinationName());
                        }
                        if (StringUtils.isNotBlank(rideListPresenterDTO.getOriginName())) {
                            vo.setOriginName(rideListPresenterDTO.getOriginName());
                        }
                        if (StringUtils.isNotBlank(rideListPresenterDTO.getDestinationName())) {
                            vo.setDestinationName(rideListPresenterDTO.getDestinationName());
                        }
                        vo.setPricingMethod("计价器计价");
                        //支付信息
                        if (null != rideListPresenterDTO.getRideOrderAmount()) {
                            vo.setAmount(rideListPresenterDTO.getRideOrderAmount());
                        }
                        if (null != rideListPresenterDTO.getRideOrderPaidThrough()) {
                            vo.setPaidThrough(rideListPresenterDTO.getRideOrderPaidThrough().getDesc());
                        }
                        if (null != rideListPresenterDTO.getRideOrderState()) {
                            vo.setPaidState(rideListPresenterDTO.getRideOrderState().getDesc());
                            vo.setPaidStateEn(rideListPresenterDTO.getRideOrderState());
                        }
                        if (null != rideListPresenterDTO.getRideState()) {
                            //vo.setOrderState(rideListPresenterDTO.getRideState().getDesc());
                            if (4 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState("到达未付款");
                                vo.setOrderStateEn("ended");
                            } else if (5 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState("已付款待评价");
                                vo.setOrderStateEn("completed");
                            } else if (3 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState("乘客已上车");
                                vo.setOrderStateEn("started");
                            } else if (2 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState("已接单");
                                vo.setOrderStateEn("pickuping");
                            } else if (1 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState("已接受预约");
                                vo.setOrderStateEn("contracted");
                            } else if (6 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState(rideListPresenterDTO.getRideState().getDesc());
                                vo.setOrderStateEn("marked");
                            } else if (7 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState(rideListPresenterDTO.getRideState().getDesc());
                                vo.setOrderStateEn("cancelled");
                            } else if (8 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState(rideListPresenterDTO.getRideState().getDesc());
                                vo.setOrderStateEn("forcecancelled");
                            } else if (9 == rideListPresenterDTO.getRideState().getCode()) {
                                vo.setOrderState(rideListPresenterDTO.getRideState().getDesc());
                                vo.setOrderStateEn("inarea");
                            }
                        }
                        orderManageVos.add(vo);
                    }
                }
                return orderManageVos;
            } catch (Exception e) {
                log.error("获取异常订单异常:{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }, customPool).exceptionally(ex -> {
            log.error("获取异常订单异常:{}", ex.getMessage());
            return null;
        });
        //代驾
        CompletableFuture<List<OrderManageVo>> proxyDrivingFuture = CompletableFuture.supplyAsync(() -> {
            try {
                List<OrderManageVo> proxyDriving = designatedService.getProxyDrivingList(adminUser, query);
                return proxyDriving;
            } catch (Exception e) {
                log.error("获取代驾订单异常:{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }, customPool).exceptionally(ex -> {
            log.error("获取代驾订单异常:{}", ex.getMessage());
            return null;
        });
        CompletableFuture<Void> all = CompletableFuture.
                allOf(onlineOrderFuture, oneClickFuture, elderlyFuture, scanCodeFuture, abnormalFuture, proxyDrivingFuture);
        CompletableFuture<OrderManageAllVo> listCompletableFuture = all.thenApply(r -> {
            log.info("所有订单已完成");
            List<OrderManageVo> orderManageJoin = onlineOrderFuture.join();
            if (CollectionUtils.isNotEmpty(orderManageJoin)) {
                list.addAll(orderManageJoin);
                log.info("线上订单列表数量:{}", orderManageJoin.size());
            }
            List<OrderManageVo> oneClickJoin = oneClickFuture.join();
            if (CollectionUtils.isNotEmpty(oneClickJoin)) {
                list.addAll(oneClickJoin);
                log.info("一键叫车行程列表数量:{}", oneClickJoin.size());
            }
            List<OrderManageVo> elderlyJoin = elderlyFuture.join();
            if (CollectionUtils.isNotEmpty(elderlyJoin)) {
                list.addAll(elderlyJoin);
                log.info("助老屏列表数量:{}", elderlyJoin.size());
            }
            List<OrderManageVo> scanCodeJoin = scanCodeFuture.join();
            if (CollectionUtils.isNotEmpty(scanCodeJoin)) {
                list.addAll(scanCodeJoin);
                log.info("扫码行程列表数量:{}", scanCodeJoin.size());
            }
            List<OrderManageVo> abnormalJoin = abnormalFuture.join();
            if (CollectionUtils.isNotEmpty(abnormalJoin)) {
                list.addAll(abnormalJoin);
                log.info("异常订单列表数量:{}", abnormalJoin.size());
            }
            List<OrderManageVo> proxyDrivingJoin = proxyDrivingFuture.join();
            if (CollectionUtils.isNotEmpty(proxyDrivingJoin)) {
                list.addAll(proxyDrivingJoin);
                log.info("代驾列表数量:{}", proxyDrivingJoin.size());
            }
            if (CollectionUtils.isNotEmpty(list)) {
                //按照时间排序
                List<OrderManageVo> timeResult = list.stream().sorted(Comparator.comparing(OrderManageVo::getOrderTime).reversed()).collect(Collectors.toList());
                //过滤
                List<OrderManageVo> distinct = timeResult.stream().distinct().collect(Collectors.toList());
                //分页
                List<OrderManageVo> collect = distinct.stream().skip((query.getPageNum() - 1) * query.getPageSize()).limit(query.getPageSize()).collect(Collectors.toList());
                log.info("过滤当前全部的查询数量:{},结果:{}", distinct.size(), JSONObject.toJSONString(distinct));
                allVo.setTotal(distinct.size());
                allVo.setVolist(collect);
                allVo.setPageNum(query.getPageNum());
                allVo.setPageSize(query.getPageSize());
                return allVo;
            }
            return allVo;
        });
        try {
            OrderManageAllVo orderManageVos = listCompletableFuture.get();
            return orderManageVos;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    private Dict calculateDriverCommission(Ride ride, JSONObject callRouteJsonObject, BigDecimal tollAmount, BigDecimal otherAmount) {
        Dict resultDict = new Dict();
        // 获取规则详细信息
        JSONObject ruleJson = callRouteJsonObject.getJSONObject("rule");
        JSONArray ruleDetailArray = ruleJson.getJSONArray("ruleDetails");

        Optional<RuleDetail> ruleDetail = OnlineValuationTimeMatcherHandler.matchRules(ruleDetailArray, DateUtil.formatDateTime(ride.getCreatedAt()).toString());
        if (!ruleDetail.isPresent()) {
            throw new IllegalArgumentException("线上车费计算失败！未找到符合规则");
        }

        // 获取司机抽成规则
        if (StrUtil.isNotBlank(ruleDetail.get().getDriverCommissionRule())) {
            OnlinePriceFlagDto onlinePriceFlagDto = JSON.parseObject(ruleDetail.get().getDriverCommissionRule(), OnlinePriceFlagDto.class);
            // 获取费用项和对应的字段
            JSONObject onlinePriceObj = callRouteJsonObject.getJSONObject("onlinePrice");
            Map<String, BigDecimal> feeMap = new HashMap<>();
            feeMap.put("startingFee", getBigDecimalOrDefault(onlinePriceObj, "startingFee", BigDecimal.ZERO));
            feeMap.put("badWeatherFee", getBigDecimalOrDefault(onlinePriceObj, "badWeatherFee", BigDecimal.ZERO));
            feeMap.put("waitingFee", BigDecimal.ZERO);
            feeMap.put("exceedMileageFee", getBigDecimalOrDefault(onlinePriceObj, "exceedMileageFee", BigDecimal.ZERO));
            feeMap.put("otherFee", otherAmount);
            feeMap.put("exceedTimeFee", getBigDecimalOrDefault(onlinePriceObj, "exceedTimeFee", BigDecimal.ZERO));
            feeMap.put("tollFee", tollAmount);
            feeMap.put("holidayFee", getBigDecimalOrDefault(onlinePriceObj, "holidayFee", BigDecimal.ZERO));
            feeMap.put("emptyBackFee", getBigDecimalOrDefault(onlinePriceObj, "emptyBackFee", BigDecimal.ZERO));
            feeMap.put("priceMarkup", Convert.toBigDecimal(ride.getPriceMarkup()));

            // 计算司机抽成
            BigDecimal driverCommissionAmount = feeMap.entrySet().stream().filter(entry -> {
                        Boolean flag = onlinePriceFlagDto.getOption().getBool(entry.getKey());
                        return flag != null && flag;
                    })  // 仅计算规则中存在的费用项 并且包含的字段值为true
                    .map(entry -> entry.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);  // 将所有费用累加起来


            //司机所得其他费用
            BigDecimal ratio = StrUtil.isNotBlank(onlinePriceFlagDto.getRatio()) ? new BigDecimal("1.00").subtract(Convert.toBigDecimal(onlinePriceFlagDto.getRatio())) : BigDecimal.ZERO;
            Boolean otherFeeBool = onlinePriceFlagDto.getOption().getBool("otherFee");
            if (otherFeeBool) {
                resultDict.put("otherFee", ratio.multiply(otherAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
            //司机所得加价
            Boolean priceMarkupBool = onlinePriceFlagDto.getOption().getBool("priceMarkup");
            if (priceMarkupBool) {
                resultDict.put("priceMarkup", ratio.multiply(Convert.toBigDecimal(ride.getPriceMarkup())).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
            //司机应得过路过桥费
            Boolean tollFeeBool = onlinePriceFlagDto.getOption().getBool("tollFee");
            if (tollFeeBool) {
                resultDict.put("tollFee", ratio.multiply(tollAmount).setScale(2, BigDecimal.ROUND_HALF_UP));
            }

            // 乘以比例，计算最终司机抽成金额
            BigDecimal driverCommission = driverCommissionAmount.multiply(new BigDecimal(onlinePriceFlagDto.getRatio())).setScale(2, BigDecimal.ROUND_HALF_UP);
            resultDict.put("driverCommissionAmount", driverCommission);
        }

        return resultDict;
    }

    // 获取 BigDecimal 值，如果为空则返回默认值
    public static BigDecimal getBigDecimalOrDefault(JSONObject jsonObject, String key, BigDecimal defaultValue) {
        BigDecimal result = jsonObject.getBigDecimal(key);
        return result != null ? result : defaultValue;
    }


    @Override
    public RestResult<Boolean> orderRefundNew(AdminUser adminUser, Long rideId, BigDecimal refundAmount, String refundType, String refundReason) {
        log.info("开始执行退款操作,行程ID:{}", rideId);
        if ("PART".equals(refundType)) {
            String amountStr = NumberUtil.toStr(refundAmount);
            String[] parts = amountStr.split("\\.");
            if (parts.length > 2) { // 有小数部分
                return RestResult.failed("退款金额最多只能有2位小数");

            }
        }
        Ride ride = rideMapper.selectById(rideId);
        if (ObjectUtil.isEmpty(ride)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        // 判断该行程是否存在已付款的订单
        RideOrder rideOrder = rideLogic.getPaidOrderByRideId(rideId);
        if (!Objects.nonNull(rideOrder)) {
            return RestResult.failed("此行程没有已付款订单");
        }

        // 订单已退款
        if (rideOrderLogic.hasBeenRefunded(rideOrder)) {
            return RestResult.failed("此行程订单在本操作前已被退款");
        }

        log.info(String.format("开始行程退款，行程ID [%d]", rideId));
        try {
            Boolean refundResult = refundService.refund(ride.getRefId(), ride.getId(), ride.getCategory(), "order", refundAmount, refundType, refundReason, adminUser.getName());
            if (!refundResult) {
                return RestResult.failed("退款失败");
            }
        } catch (Exception e) {
            return RestResult.failed(e.getMessage());
        }

        return RestResult.success();
    }

    @Override
    public RestResult refundListByRideId(Long rideId) {
        List<RideRefundLog> rideRefundLogs = rideRefundLogMapper.selectList(Wrappers.<RideRefundLog>lambdaQuery().eq(RideRefundLog::getRideId, rideId));
        return RestResult.success(rideRefundLogs);
    }

}